Loading...
Logo
Processing Forum
Hello, 
When I press mouse I want ellipse to animate for few seconds, then I want it to disappear from memory. 
It shouldn't be inside main processing draw().
I tried a Thread, but ellipse has ugly flicker all the time:

Copy code
  1. SimpleThread thread1;

  2. void setup()
  3. {
  4.   size(400,300);
  5. }

  6. void draw()
  7. {
  8.     background(0);
  9.     float x=sin(frameCount*.01)*100+width/2;
  10.     float y=cos(frameCount*.01)*100+height/2;
  11.     ellipse(x,y,40,40);
  12. }

  13. void mousePressed()
  14. {
  15.   thread1 = new SimpleThread(5,"cat");
  16.   thread1.start(new PVector(mouseX, mouseY));
  17. }

Copy code
  1. // Class taken from http://www.shiffman.net/teaching/a2z/threads/
  2. public class SimpleThread extends Thread{
  3.   private boolean running;           // Is the thread running?  Yes or no?
  4.   private int wait;                  // How many milliseconds should we wait in between executions?
  5.   private String id;                 // Thread name
  6.   private float count;                 // counter
  7.   private PVector p;

  8.   public SimpleThread (int w, String s) {
  9.     wait = w;
  10.     running = false;
  11.     id = s;
  12.     count = 0;
  13.     p=new PVector(0,0);
  14.   }
  15.   // Overriding "start()"
  16.   public void start (PVector p_)
  17.   {
  18.     p=p_;
  19.     // Set running equal to true
  20.     running = true;
  21.     // Print messages
  22.     System.out.println("Starting thread (will execute every " + wait + " milliseconds.)");
  23.     // Do whatever start does in Thread, don't forget this!
  24.     super.start();
  25.   }

  26.   // We must implement run, this gets triggered by start()
  27.   public void run ()
  28.   {
  29.     while (running && count < 10) {
  30.       //System.out.println(id + ": " + count);
  31.       count+=.001;
  32.       // Ok, let's wait for however long we should wait
  33.             try {
  34.        sleep((long)(wait));
  35.        }
  36.        catch (Exception e) {
  37.        }
  38.       float x=sin(frameCount*.01)*100+p.x;
  39.       float y=cos(frameCount*.01)*100+p.y;
  40.       ellipse(x,y,10,10);
  41.     }
  42.     System.out.println(id + " thread is done!");  // The thread is done when we get to the end of run()
  43.   }

  44.   // Our method that quits the thread
  45.   public void quit()
  46.   {
  47.     System.out.println("Quitting.");
  48.     running = false;  // Setting running to false ends the loop in run()
  49.     interrupt(); // in case the thread is waiting. . .
  50.   }
  51. }

Any tips appreciated.

jimmi


Replies(8)

Why should it not be inside draw()?  This approach is going to cause you all kinds of problems (there are plenty of examples of similar questions in the forum), so you need a pretty good reason to justify causing yourself the hassle...

My guess for the cause of the flicker is that the timing of your separate thread doesn't correspond with the timing of the draw() loop, but the sketch window is only updated when draw completes.  So if your thread doesn't coincide with draw refreshing the screen the ellipse won't get drawn, hence the flicker.

Why not let us know why you want to avoid putting the code into draw() - perhaps there's an alternative approach that will satisfy your needs.
Thanks for the reply!

I am writing a game with lots of classes, and I want draw() to be as clean as possible.
Here I used thread animation for popping animations, like  "game over", "you've earned a point", "2 lives left" and many more..
These animations are executed for few secs while playing the main game. The main game code is inside draw();

Is there a better way instead of putting animation into draw()?
Sounds like you might appreciate registerDraw().  Make your class public, add registerDraw(this) to your class constructor and you can add a separate draw method within your class.  There are some gotchas to this approach, but it definitely has many benefits too...

You can see it implemented here:
http://www.openprocessing.org/visuals/?visualID=6412
Thanks blindfish! registerDraw is awesome. 
here is what makes sense to me:

Copy code
  1. Circle c;

  2. void setup() {
  3.   size(500,500);
  4.   c=new Circle();
  5. }

  6. void draw() {
  7.   background(0);
  8. }

  9. void mousePressed()
  10. {
  11.   c.trigger(new PVector(mouseX, mouseY)); 
  12. }

  13. public class Circle {

  14.   PVector p;
  15.   boolean drawing;
  16.   int time=1;
  17.   int endTime=100;

  18.   Circle() {
  19.     registerDraw(this);
  20.   }

  21.   void draw() 
  22.   {
  23.     if (drawing)
  24.     {
  25.       float x = sin(frameCount*.1)*25+p.x;
  26.       float y = p.y;
  27.       ellipse(x,y,20,20);
  28.       time++;
  29.       if (time>endTime)drawing=false;
  30.     }
  31.   }

  32.   void trigger(PVector p_)
  33.   {
  34.     drawing=true;
  35.     time=0;
  36.     p=p_; 
  37.   }
  38. }
You can still write the drawing code to do all the little temporary things like flashing up 'game over' in other classes or methods. But the important thing is that all requests to do some drawing should be iniated by the main the draw() loop. That way you can guarantee that all drawing is done on the same thread and so avoid flickering problems.

A fairly standard way of doing this in processing would be something like this in your main sketch:

draw()
{
      // Normal game drawing stuff here

      otherObject1.draw(this);
      otherObject2.draw(this);
}

And this in each of your other classes 

OtherClass()
{
      void draw(PApplet parent)
      {
            // Other object's drawing happens here.
      }
}

Those other objects can keep track of whether they need to display anything at all (such as a 'game over'). If they don't need to draw anything, they can just return straight away with little cost to the speed of your main draw() loop. If they do need to draw, they have a handle to the main sketch (' parent') so can do standard Processing drawing operations. Those other objects can also keep track of their own time so that they can animate for a fixed number of draw cycles or seconds.

This way keeps your code uncluttered, is pretty object-oriented and ensures all drawing is done on the same thread.
I don't understand the initial problem. The way I usually do is this:

Copy code
  1. ArrayList things = new ArrayList();

  2. class Sample
  3. {
  4.   ...

  5.    void update()
  6.    {
  7.             mathAndLogicUpdate();
  8.             display();
  9.    }

  10.    void display()
  11.    {
  12.       //class object drawing routines here
  13.     }
  14.   ...
  15. }

  16. //////////////////////////////////////////////////////DISTINCT FILE //////////////////////////////

  17. void setup()
  18. {
  19.       things.add(new Sample);
  20.       things.add(new Sample);
  21.       things.add(new Sample);
  22.       things.add(new Sample);
  23. }


  24. //////////////////////////////////////////////////////DISTINCT FILE //////////////////////////////

  25. void draw()
  26. {
  27.       updateWorld();
  28. }


  29. /////////////////////////////////////////DISTINCT FILE////////////////////////////////////////

  30. void updateWorld()
  31. {
  32.      for (int i = 0; i< things.size(); i++)
  33.             {
  34.                   Sample thing = (Sample) things.get(i);
  35.                   thing.update();
  36.             } 
  37. }
See, everything is neatly hierarchied and placed into separate files, so no mess. And all is clean.
Copy code
    Copy code
      Copy code
        Copy code
          yeah, it's probably the same....
          however I'll have to write less code with registerDraw :)
          what about memory usage is it the same thing?

          registerDraw() avoids the need for additional 'class display method' calls from within the main draw loop, but essentially achieves the same result.  One of the gotchas I hinted at before is that the order your objects are drawn is dependent on the order in which registerDraw() was called on them; with later calls to registerDraw() being drawn on top.  If that's a problem you may want to use the 'class display method' approach and use conditions within the main draw loop to determine drawing order.  Alternatively you could have a controller class that determines drawing order...  Basically the best approach will depend on your needs.

          I personally like the registerDraw approach; though perhaps take it to extremes e.g.: http://www.openprocessing.org/visuals/?visualID=6890

          A couple more things to know about registerDraw.  There's an associated unregisterDraw() method, that does what it says on the tin.  Note that if you call this then the class's draw method is no longer called until registerDraw is called again - not always what you want.

          One other gotcha I know about: unless it's now been fixed, it is possible to call registerDraw multiple times on the same object.  This is bad!  You land up running the object's draw() method multiple times in the same frame...