Olof,

I'm not sure of where the "mad update" is coming from, but you
don't want to call update() from paint; that's actually backwards
from what the system expects.

From the Component javadocs:
       The update method of Component calls this component's paint
       method to redraw this component.
and:
       Subclasses of Component that override this method should
       either call super.update(g), or call paint(g) directly
       from their update method.

Update calls paint() internally, which means that it calls
your paint, which calls update, which ...

Of course, you've overridden update(), so this changes the
behavior, but it's a bit confusing at the least.  But there could
be more wrong here: it could be that by changing the nature of
update/paint interaction, you're getting in the way of the
regular system of issuing and consuming repaint() events, which
could cause the paint calls to keep being issued.

The solution here is to simply override paint() and do your
painting there.  Or if you're using Swing, override paintComponent()
instead.  Don't override update, or at least not in the manner you
are doing currently.

To improve performance in general:
       - use a timer to schedule regular repaints so you don't get
       swamped with constant repaint events (similar to what you're
       doing, but I don't follow the complexity of using key actions
       for this.  Why not simply issue a repaint call?)
       - only draw the area that's changed.  So if only one rectangle
       of the playing area has changed, draw that updated region
       into the back buffer, and copy that region of the back buffer
       into the window.

Chet.


Olof Bjarnason wrote:
Hi there!

I am new to the list, I hope I found the right list to ask this
question, otherwise i appologize and ask for directions of which list
is more appropriate.

I am developing an Applet based 2d game ( a minimalistic SimCity clone
). In an attempt to decrease flickering I skip the
erase-to-background-color default behaviour of paint() by overriding
it and putting my drawing code there instead. paint(Graphics g) simply
calls update(g), as per recommendation in Java API docs:

      public void update(Graphics g) {
              // Background: map field
              g.drawImage(backbuffer, 0, 0, this);

              // Foreground: headsup display
              headsup.draw(g);
      }

      public void paint(Graphics g) {
              update(g);
      }

The headsup-display draws some lines ontop of the background map
image, for example the cursor.

Now the problem is that even though the window (Firefox or
AppletViewer) is left unresized and nothing obscures it, the
update-method gets called repeatedly without-end, giving
less-than-optimal performance, and a lot of flickering.

Even more strangely, when starting the Applet, it works fine (update()
gets called once a second..) for a some 5-10 seconds, then the mad
update()-calling begins. I'm under WinXP, JRE1.4.2. The continuous
update:ing really hogs the CPU (gets up to 90%) which is not good for
a game supposed to be run on a web page while the user listens to
music for example.

Technical details:

In order to drive the simulation, I have a background thread which
approximately once a second fires an ActionEvent on a phony Button
which is a member field of the Applet:

      private Button triggerStepButton;

      public void run() {
              Thread.currentThread().setPriority(1);
              while (running) {
                      ActionEvent ae = new ActionEvent(this.triggerStepButton,
                                      ActionEvent.ACTION_PERFORMED, "");
                      
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ae);
                      try {
                              Thread.sleep(1000);
                      } catch (InterruptedException e) {
                              e.printStackTrace();
                      }
              }
      }

run() is a method of my Applet, aswell as triggerStepButton.
triggerStepButton has one listener: the Applet. In the init() method
of the Applet:

              triggerStepButton = new Button();
              triggerStepButton.addActionListener(this);

So, the Applet has the following signature:

   public class TerraformerApplet extends Applet implements Runnable,
ActionListener { ...

The actionPerformed method of the Applet looks like this:

      public void actionPerformed(ActionEvent e) {
              model.step();
              updateBackbuffer();
              repaint();
      }

... where model contains the SimCity model and it's specific rules.
updateBackbuffer updates the parts of the background image (called
backbuffer) which have changed since last call. The actionPerformed
method is called once a second, even after the mad update:ing has
begun.

Why not call model.step() and updateBackbuffer() in run()? Well I want
to avoid the synchronization hassle needed to make only one thread
access the model/background image at-a-time. This solution is simpler,
even though it might seem slightly complicated at a first glance. I
tried the synchronization solution first, but then I remembered that
the whole event-queue system is built around the idea of running ONE
EVENT AT A TIME, so it seemed natural to squeeze in the
step()-triggering into it. I assume the postEvent-method is
synchronized?

So, does anyone have any idea what is going on? Somehow I get the
feeling the repaint() queries are not "eaten up" in the event queue,
as if there is supposed to be some way to do a consume(e), analogous
to KeyEvent's, but the API docs gives no hint of this. Or, I got an
infinite loop calling repaint() somewhere, which is triggered after a
few seconds of the Applet running. Both seem far-fetched at the
moment...

Thanks for any answers,

/Olof

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to