Skip to main content

[JAVA2D] Problem with non-stopping calls to update()

22 replies [Last post]
Anonymous

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 listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Jim Graham

>> What happens right before the trigger? You could try overriding
>> repaint()
> repaint() is not getting called excessively. It is only update() that
> gets called all the time. I know this since I tried this:
>
> public void repaint() {
> System.out.println("repaint");
> super.repaint();
> }
>
> .. without "repaint" being printed every time "update" was printed
> (did the same thing for update() )

I don't understand this statement. Are you saying that update() was being
called more times than repaint()?

Also, note that there are several flavors of repaint() and any of them lead
to update() being called...

...jim

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

On 8/25/05, Jim Graham wrote:
>
> >> What happens right before the trigger? You could try overriding
> >> repaint()
> > repaint() is not getting called excessively. It is only update() that
> > gets called all the time. I know this since I tried this:
> >
> > public void repaint() {
> > System.out.println("repaint");
> > super.repaint();
> > }
> >
> > .. without "repaint" being printed every time "update" was printed
> > (did the same thing for update() )
>
> I don't understand this statement. Are you saying that update() was being
> called more times than repaint()?

Sorry for crypting writing, yes that is what I mean. repaint is called
a lot less times than update.

>
> Also, note that there are several flavors of repaint() and any of them lead
> to update() being called...
>
> ...jim
>
>
Still, I tried removing ALL repaint calls from my code, and overriding
both update and paint (in the manner you described with paint doing
the painting and update calling paint). Still same ..

/Olof

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Jim Graham

>> 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.
>
> OK, guess I misread the docs. Actually, I followed this tutorial to begin
> with: http://www.dgp.toronto.edu/~mjmcguff/learn/java/

either direction will work as long as you override both. Our docs show the
guts in paint() and then update() redirecting to paint() since it reflects
what would otherwise go on underneath the covers. Typically an animation
program overrides paint() to start out with to draw a frame, because that
is where a program should put its paint() code and that is where someone
reading the code would go first to find the painting code. The override of
update() is then added to stop the "erase to background color" flickering.
When you look at it that way, it seems more logical to have the actual
painting code in the paint() method, but both work as long as you override
both.

>> 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.
> I'm using AWT I guess, no Swing. I'm trying to go for old-API in order
> to make the game runnable on more computers. I compile for 1.4.2, but
> I guess 1.4.2 has Swing so I could go for paintComponent, but my
> feeling is I should use paint(), eg.the tutorial uses paint().
> Comments?

I don't see how the way you've overridden paint/update() can lead to the
problem in and of itself. It would be an interesting experiment, but I
wouldn't abandon your architecture to try to fix this.

>> 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?)

This is a hard call. While I still need to think about the ramifications
of what you've done with sending ActionEvents to yourself, simply using a
Timer instead of rolling your own Thread would not change anything here if
the action of the Timer was to send the ActionEvent.

If you switched to periodic repaint() calls instead of sending an
ActionEvent then it would mean that the calls to update() would happen
directly instead of as a result of a frame update. You would either have
to move the frame update code to the update() method, or you would have to
have two timer events - one to update the frame, and another to call
repaint - and the two would happen asynchronously.

This points out a potential problem with the way you've written the code
and could be the root cause of the flood of repaints. Are there ever any
frames that take longer than 1 second to render? If so, then there is no
inherent throttling of your ActionEvents to match the extended compute
time. If, say, you have one frame update that takes 10 seconds to
complete, then by the time it is done, there will be 10 ActionEvents in the
queue waiting to be processed. If those events take less time to process
then you will run through all 10 of them at once and see 10 updates very
quickly in a row which could look like what is happening to you. If it is
much more likely to encounter frame updates that take longer than 1 second
then the backup will be constantly increasing.

Instead of sending an ActionEvent every second which forces a frame update,
you might want to have some way of creating back-pressure. Either:

- have something in your frame update code which requests the subsequent
frame when it is done and don't send another ActionEvent until it is
requested - that guarantees a delay of N milliseconds "between" frames so
if frames take longer than your delay, the ActionEvents don't accumulate.
This is kind of hard to implement, though.

- have your frame update code check the last time a frame was updated and
if it was less than 1 second ago, skip this ActionEvent to catch up
(another will come along in less than a second).

- you can also look at the time-stamp of the ActionEvent and if it was sent
more than 1 second ago, skip it in favor of one that you know will be
coming along very soon.

- have your frame update code increment "number of frames handled" and have
the event sending code increment "number of frames requested" and if the
requested count is too far ahead of the handled count (like more than 1
greater), skip a beat by not sending the ActionEvent this time.

- use calls to update to trigger your frame updates and use "timed repaint"
events which coalesce:

Timer thread {
loop {
sleep(1000);
repaint(10); // Will coalesce with other repaint(ms) calls
}
}

update(Graphics g) {
updateframe();
paint(g);
}

paint(Graphics g) {
g.drawImage(backbuffer);
drawheadsup(g);
}

Note that calls to repaint() with no delay will be queued and result in
calls to update() on a 1 for 1 basis so you could end up with the same
backlog, but calls to repaint() with a delay (as above) will be coalesced
with each other.

>> - 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.

That will help keep the frame update code from getting too far behind the
event sending thread...

...jim

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

This is a very thourough answer. I will try to reply ...

On 8/25/05, Jim Graham wrote:
> >> 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.
> >
> > OK, guess I misread the docs. Actually, I followed this tutorial to begin
> > with: http://www.dgp.toronto.edu/~mjmcguff/learn/java/
>
> either direction will work as long as you override both. Our docs show the
> guts in paint() and then update() redirecting to paint() since it reflects
> what would otherwise go on underneath the covers. Typically an animation
> program overrides paint() to start out with to draw a frame, because that
> is where a program should put its paint() code and that is where someone
> reading the code would go first to find the painting code. The override of
> update() is then added to stop the "erase to background color" flickering.
> When you look at it that way, it seems more logical to have the actual
> painting code in the paint() method, but both work as long as you override
> both.
I'm with you and I tried both, same result.

>
> >> 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.
> > I'm using AWT I guess, no Swing. I'm trying to go for old-API in order
> > to make the game runnable on more computers. I compile for 1.4.2, but
> > I guess 1.4.2 has Swing so I could go for paintComponent, but my
> > feeling is I should use paint(), eg.the tutorial uses paint().
> > Comments?
>
> I don't see how the way you've overridden paint/update() can lead to the
> problem in and of itself. It would be an interesting experiment, but I
> wouldn't abandon your architecture to try to fix this.
I started "porting" my Applet to JApplet but it proved horrendously
errorprone (basically had to cut the file in three --- more work to
fix this than starting from scratch) so I am back at the
AWT/paint/update stage again.

>
> >> 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?)
>
> This is a hard call. While I still need to think about the ramifications
> of what you've done with sending ActionEvents to yourself, simply using a
> Timer instead of rolling your own Thread would not change anything here if
> the action of the Timer was to send the ActionEvent.
I've tried both, same result. A potential error with my previous
"virtual-click-a-button" method was that it used the postEvent from a
custom thread. Given that the documents state that all AWT/Swing code
should execute using the invokeLater technique, this i not
recommended. Anyway, the Swing Timer didn't work either in my setting.

>
> If you switched to periodic repaint() calls instead of sending an
> ActionEvent then it would mean that the calls to update() would happen
> directly instead of as a result of a frame update. You would either have
> to move the frame update code to the update() method, or you would have to
> have two timer events - one to update the frame, and another to call
> repaint - and the two would happen asynchronously.
>
> This points out a potential problem with the way you've written the code
> and could be the root cause of the flood of repaints. Are there ever any
> frames that take longer than 1 second to render? If so, then there is no
> inherent throttling of your ActionEvents to match the extended compute
> time. If, say, you have one frame update that takes 10 seconds to
> complete, then by the time it is done, there will be 10 ActionEvents in the
> queue waiting to be processed. If those events take less time to process
> then you will run through all 10 of them at once and see 10 updates very
> quickly in a row which could look like what is happening to you. If it is
> much more likely to encounter frame updates that take longer than 1 second
> then the backup will be constantly increasing.
Simple answer: no. My updateBackbuffer code paints at most 64 tile
images sized 32x32 each, and actually even when the
non-stopping-updates is going on, there is no performance problem more
than the CPU getting up to like 10% (I'm sorry stated 90% earlier post
but that was a misreading must have been something else..). The way I
know there is mad-updating is via the console output (println) and
flickering (the headsup display widgets are flickering).

>
> Instead of sending an ActionEvent every second which forces a frame update,
> you might want to have some way of creating back-pressure. Either:
>
> - have something in your frame update code which requests the subsequent
> frame when it is done and don't send another ActionEvent until it is
> requested - that guarantees a delay of N milliseconds "between" frames so
> if frames take longer than your delay, the ActionEvents don't accumulate.
> This is kind of hard to implement, though.
>
> - have your frame update code check the last time a frame was updated and
> if it was less than 1 second ago, skip this ActionEvent to catch up
> (another will come along in less than a second).
>
> - you can also look at the time-stamp of the ActionEvent and if it was sent
> more than 1 second ago, skip it in favor of one that you know will be
> coming along very soon.
>
> - have your frame update code increment "number of frames handled" and have
> the event sending code increment "number of frames requested" and if the
> requested count is too far ahead of the handled count (like more than 1
> greater), skip a beat by not sending the ActionEvent this time.
>
> - use calls to update to trigger your frame updates and use "timed repaint"
> events which coalesce:
>
> Timer thread {
> loop {
> sleep(1000);
> repaint(10); // Will coalesce with other repaint(ms) calls
> }
> }
>
> update(Graphics g) {
> updateframe();
> paint(g);
> }
>
> paint(Graphics g) {
> g.drawImage(backbuffer);
> drawheadsup(g);
> }
>
> Note that calls to repaint() with no delay will be queued and result in
> calls to update() on a 1 for 1 basis so you could end up with the same
> backlog, but calls to repaint() with a delay (as above) will be coalesced
> with each other.
>
> >> - 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.
>
> That will help keep the frame update code from getting too far behind the
> event sending thread...
>
> ...jim
>
>
Thanks for your time,

/Olof

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

OK I've done some debug-printing for you to get a feeling of the
behaviour. I use this debug-println:

public static void println(String str) {
long millis = System.currentTimeMillis() - startMillis;
String threadName = Thread.currentThread().getName();
System.out.println("T="+millis+"\t"+threadName + ": " + str);
}

... which give me quite a lot of information. This is the printout
from a typical 5-second run:
(WARNING: many lines below!)

(ms) (name of thread) (message)
T=0 thread applet-terraformer.TerraformerApplet.class: Setting up model.
T=0 thread applet-terraformer.TerraformerApplet.class: Setting up
graphics fundaments.
T=0 thread applet-terraformer.TerraformerApplet.class: Loading resources.
T=10 thread applet-terraformer.TerraformerApplet.class: Downloading images.
T=120 thread applet-terraformer.TerraformerApplet.class: Creating backbuffer.
T=130 thread applet-terraformer.TerraformerApplet.class: Creating
headsup display.
T=130 thread applet-terraformer.TerraformerApplet.class: Setting up
rendering state.
T=130 AWT-EventQueue-1: Accepting keyboard input once focused.
T=130 AWT-EventQueue-1: Doing first background render.
T=130 AWT-EventQueue-1: updateBackbuffer
T=130 AWT-EventQueue-1: repaint
T=130 AWT-EventQueue-1: paint
T=140 AWT-EventQueue-1: headsup.draw

T=1132 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
T=1132 AWT-EventQueue-1: model.step
T=1132 AWT-EventQueue-1: updateBackbuffer
T=1132 AWT-EventQueue-1: repaint
T=1132 AWT-EventQueue-1: update
T=1132 AWT-EventQueue-1: paint
T=1132 AWT-EventQueue-1: headsup.draw

T=2133 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
T=2133 AWT-EventQueue-1: model.step
T=2133 AWT-EventQueue-1: updateBackbuffer
T=2133 AWT-EventQueue-1: repaint
T=2133 AWT-EventQueue-1: update
T=2133 AWT-EventQueue-1: paint
T=2133 AWT-EventQueue-1: headsup.draw

T=3135 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
T=3145 AWT-EventQueue-1: model.step
T=3145 AWT-EventQueue-1: updateBackbuffer
T=3165 AWT-EventQueue-1: repaint
T=3165 AWT-EventQueue-1: update
T=3165 AWT-EventQueue-1: paint
T=3165 AWT-EventQueue-1: headsup.draw
T=3205 AWT-EventQueue-1: update
T=3205 AWT-EventQueue-1: paint
T=3205 AWT-EventQueue-1: headsup.draw
T=3245 AWT-EventQueue-1: update
T=3245 AWT-EventQueue-1: paint
T=3245 AWT-EventQueue-1: headsup.draw
T=3285 AWT-EventQueue-1: update
T=3285 AWT-EventQueue-1: paint
T=3285 AWT-EventQueue-1: headsup.draw
T=3325 AWT-EventQueue-1: update
T=3325 AWT-EventQueue-1: paint
T=3325 AWT-EventQueue-1: headsup.draw
T=3365 AWT-EventQueue-1: update
T=3365 AWT-EventQueue-1: paint
T=3365 AWT-EventQueue-1: headsup.draw
T=3405 AWT-EventQueue-1: update
T=3405 AWT-EventQueue-1: paint
T=3405 AWT-EventQueue-1: headsup.draw
T=3445 AWT-EventQueue-1: update
T=3445 AWT-EventQueue-1: paint
T=3445 AWT-EventQueue-1: headsup.draw
T=3495 AWT-EventQueue-1: update
T=3495 AWT-EventQueue-1: paint
T=3495 AWT-EventQueue-1: headsup.draw
T=3535 AWT-EventQueue-1: update
T=3535 AWT-EventQueue-1: paint
T=3535 AWT-EventQueue-1: headsup.draw
T=3575 AWT-EventQueue-1: update
T=3575 AWT-EventQueue-1: paint
T=3575 AWT-EventQueue-1: headsup.draw
T=3615 AWT-EventQueue-1: update
T=3615 AWT-EventQueue-1: paint
T=3615 AWT-EventQueue-1: headsup.draw
T=3655 AWT-EventQueue-1: update
T=3655 AWT-EventQueue-1: paint
T=3655 AWT-EventQueue-1: headsup.draw
T=3705 AWT-EventQueue-1: update
T=3705 AWT-EventQueue-1: paint
T=3705 AWT-EventQueue-1: headsup.draw
T=3745 AWT-EventQueue-1: update
T=3745 AWT-EventQueue-1: paint
T=3745 AWT-EventQueue-1: headsup.draw
T=3786 AWT-EventQueue-1: update
T=3786 AWT-EventQueue-1: paint
T=3786 AWT-EventQueue-1: headsup.draw
T=3826 AWT-EventQueue-1: update
T=3826 AWT-EventQueue-1: paint
T=3826 AWT-EventQueue-1: headsup.draw
T=3866 AWT-EventQueue-1: update
T=3866 AWT-EventQueue-1: paint
T=3866 AWT-EventQueue-1: headsup.draw
T=3906 AWT-EventQueue-1: update
T=3906 AWT-EventQueue-1: paint
T=3916 AWT-EventQueue-1: headsup.draw
T=3956 AWT-EventQueue-1: update
T=3956 AWT-EventQueue-1: paint
T=3956 AWT-EventQueue-1: headsup.draw
T=3996 AWT-EventQueue-1: update
T=3996 AWT-EventQueue-1: paint
T=3996 AWT-EventQueue-1: headsup.draw
T=4036 AWT-EventQueue-1: update
T=4036 AWT-EventQueue-1: paint
T=4036 AWT-EventQueue-1: headsup.draw
T=4076 AWT-EventQueue-1: update
T=4076 AWT-EventQueue-1: paint
T=4076 AWT-EventQueue-1: headsup.draw
T=4126 AWT-EventQueue-1: update
T=4126 AWT-EventQueue-1: paint
T=4126 AWT-EventQueue-1: headsup.draw

T=4136 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
T=4136 AWT-EventQueue-1: model.step
T=4136 AWT-EventQueue-1: updateBackbuffer
T=4136 AWT-EventQueue-1: repaint
T=4136 AWT-EventQueue-1: update
T=4136 AWT-EventQueue-1: paint
T=4136 AWT-EventQueue-1: headsup.draw
T=4166 AWT-EventQueue-1: update
T=4166 AWT-EventQueue-1: paint
T=4166 AWT-EventQueue-1: headsup.draw
T=4206 AWT-EventQueue-1: update
T=4206 AWT-EventQueue-1: paint
T=4206 AWT-EventQueue-1: headsup.draw
T=4256 AWT-EventQueue-1: update
T=4256 AWT-EventQueue-1: paint
T=4256 AWT-EventQueue-1: headsup.draw
T=4296 AWT-EventQueue-1: update
T=4296 AWT-EventQueue-1: paint
T=4296 AWT-EventQueue-1: headsup.draw
T=4366 AWT-EventQueue-1: update
T=4366 AWT-EventQueue-1: paint
T=4366 AWT-EventQueue-1: headsup.draw
T=4406 AWT-EventQueue-1: update
T=4406 AWT-EventQueue-1: paint
T=4406 AWT-EventQueue-1: headsup.draw
T=4446 AWT-EventQueue-1: update
T=4446 AWT-EventQueue-1: paint
T=4446 AWT-EventQueue-1: headsup.draw
T=4487 AWT-EventQueue-1: update
T=4487 AWT-EventQueue-1: paint
T=4487 AWT-EventQueue-1: headsup.draw
T=4527 AWT-EventQueue-1: update
T=4527 AWT-EventQueue-1: paint
T=4527 AWT-EventQueue-1: headsup.draw
T=4577 AWT-EventQueue-1: update
T=4577 AWT-EventQueue-1: paint
T=4577 AWT-EventQueue-1: headsup.draw
T=4617 AWT-EventQueue-1: update
T=4617 AWT-EventQueue-1: paint
T=4617 AWT-EventQueue-1: headsup.draw
T=4657 AWT-EventQueue-1: update
T=4657 AWT-EventQueue-1: paint
T=4657 AWT-EventQueue-1: headsup.draw
T=4697 AWT-EventQueue-1: update
T=4697 AWT-EventQueue-1: paint
T=4697 AWT-EventQueue-1: headsup.draw

As you can see, the mad-updating begins at T=3205 and continues then
on. Note that the actionPerformed from the Swing-Timer is still
functioning, and that the method that keeps getting called is update
(which in turn calls paint, which call headsup.draw).

/Olof

On 8/25/05, Olof Bjarnason
wrote:
> This is a very thourough answer. I will try to reply ...
>
> On 8/25/05, Jim Graham wrote:
> > >> 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.
> > >
> > > OK, guess I misread the docs. Actually, I followed this tutorial to begin
> > > with: http://www.dgp.toronto.edu/~mjmcguff/learn/java/
> >
> > either direction will work as long as you override both. Our docs show the
> > guts in paint() and then update() redirecting to paint() since it reflects
> > what would otherwise go on underneath the covers. Typically an animation
> > program overrides paint() to start out with to draw a frame, because that
> > is where a program should put its paint() code and that is where someone
> > reading the code would go first to find the painting code. The override of
> > update() is then added to stop the "erase to background color" flickering.
> > When you look at it that way, it seems more logical to have the actual
> > painting code in the paint() method, but both work as long as you override
> > both.
> I'm with you and I tried both, same result.
>
> >
> > >> 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.
> > > I'm using AWT I guess, no Swing. I'm trying to go for old-API in order
> > > to make the game runnable on more computers. I compile for 1.4.2, but
> > > I guess 1.4.2 has Swing so I could go for paintComponent, but my
> > > feeling is I should use paint(), eg.the tutorial uses paint().
> > > Comments?
> >
> > I don't see how the way you've overridden paint/update() can lead to the
> > problem in and of itself. It would be an interesting experiment, but I
> > wouldn't abandon your architecture to try to fix this.
> I started "porting" my Applet to JApplet but it proved horrendously
> errorprone (basically had to cut the file in three --- more work to
> fix this than starting from scratch) so I am back at the
> AWT/paint/update stage again.
>
> >
> > >> 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?)
> >
> > This is a hard call. While I still need to think about the ramifications
> > of what you've done with sending ActionEvents to yourself, simply using a
> > Timer instead of rolling your own Thread would not change anything here if
> > the action of the Timer was to send the ActionEvent.
> I've tried both, same result. A potential error with my previous
> "virtual-click-a-button" method was that it used the postEvent from a
> custom thread. Given that the documents state that all AWT/Swing code
> should execute using the invokeLater technique, this i not
> recommended. Anyway, the Swing Timer didn't work either in my setting.
>
> >
> > If you switched to periodic repaint() calls instead of sending an
> > ActionEvent then it would mean that the calls to update() would happen
> > directly instead of as a result of a frame update. You would either have
> > to move the frame update code to the update() method, or you would have to
> > have two timer events - one to update the frame, and another to call
> > repaint - and the two would happen asynchronously.
> >
> > This points out a potential problem with the way you've written the code
> > and could be the root cause of the flood of repaints. Are there ever any
> > frames that take longer than 1 second to render? If so, then there is no
> > inherent throttling of your ActionEvents to match the extended compute
> > time. If, say, you have one frame update that takes 10 seconds to
> > complete, then by the time it is done, there will be 10 ActionEvents in the
> > queue waiting to be processed. If those events take less time to process
> > then you will run through all 10 of them at once and see 10 updates very
> > quickly in a row which could look like what is happening to you. If it is
> > much more likely to encounter frame updates that take longer than 1 second
> > then the backup will be constantly increasing.
> Simple answer: no. My updateBackbuffer code paints at most 64 tile
> images sized 32x32 each, and actually even when the
> non-stopping-updates is going on, there is no performance problem more
> than the CPU getting up to like 10% (I'm sorry stated 90% earlier post
> but that was a misreading must have been something else..). The way I
> know there is mad-updating is via the console output (println) and
> flickering (the headsup display widgets are flickering).
>
> >
> > Instead of sending an ActionEvent every second which forces a frame update,
> > you might want to have some way of creating back-pressure. Either:
> >
> > - have something in your frame update code which requests the subsequent
> > frame when it is done and don't send another ActionEvent until it is
> > requested - that guarantees a delay of N milliseconds "between" frames so
> > if frames take longer than your delay, the ActionEvents don't accumulate.
> > This is kind of hard to implement, though.
> >
> > - have your frame update code check the last time a frame was updated and
> > if it was less than 1 second ago, skip this ActionEvent to catch up
> > (another will come along in less than a second).
> >
> > - you can also look at the time-stamp of the ActionEvent and if it was sent
> > more than 1 second ago, skip it in favor of one that you know will be
> > coming along very soon.
> >
> > - have your frame update code increment "number of frames handled" and have
> > the event sending code increment "number of frames requested" and if the
> > requested count is too far ahead of the handled count (like more than 1
> > greater), skip a beat by not sending the ActionEvent this time.
> >
> > - use calls to update to trigger your frame updates and use "timed repaint"
> > events which coalesce:
> >
> > Timer thread {
> > loop {
> > sleep(1000);
> > repaint(10); // Will coalesce with other repaint(ms) calls
> > }
> > }
> >
> > update(Graphics g) {
> > updateframe();
> > paint(g);
> > }
> >
> > paint(Graphics g) {
> > g.drawImage(backbuffer);
> > drawheadsup(g);
> > }
> >
> > Note that calls to repaint() with no delay will be queued and result in
> > calls to update() on a 1 for 1 basis so you could end up with the same
> > backlog, but calls to repaint() with a delay (as above) will be coalesced
> > with each other.
> >
> > >> - 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.
> >
> > That will help keep the frame update code from getting too far behind the
> > event sending thread...
> >
> > ...jim
> >
> >
> Thanks for your time,
>
> /Olof
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Jim Graham

This is hard to tell without seeing the code in the headsup.draw method...

...jim

--On Thursday, August 25, 2005 10:19 PM +0200 Olof Bjarnason

wrote:

> OK I've done some debug-printing for you to get a feeling of the
> behaviour. I use this debug-println:
>
> public static void println(String str) {
> long millis = System.currentTimeMillis() - startMillis;
> String threadName = Thread.currentThread().getName();
> System.out.println("T="+millis+"\t"+threadName + ": " + str);
> }
>
> ... which give me quite a lot of information. This is the printout
> from a typical 5-second run:
> (WARNING: many lines below!)
>
> (ms) (name of thread) (message)
> T=0 thread applet-terraformer.TerraformerApplet.class: Setting up model.
> T=0 thread applet-terraformer.TerraformerApplet.class: Setting up
> graphics fundaments.
> T=0 thread applet-terraformer.TerraformerApplet.class: Loading resources.
> T=10 thread applet-terraformer.TerraformerApplet.class: Downloading
> images. T=120 thread applet-terraformer.TerraformerApplet.class: Creating
> backbuffer. T=130 thread applet-terraformer.TerraformerApplet.class:
> Creating headsup display.
> T=130 thread applet-terraformer.TerraformerApplet.class: Setting up
> rendering state.
> T=130 AWT-EventQueue-1: Accepting keyboard input once focused.
> T=130 AWT-EventQueue-1: Doing first background render.
> T=130 AWT-EventQueue-1: updateBackbuffer
> T=130 AWT-EventQueue-1: repaint
> T=130 AWT-EventQueue-1: paint
> T=140 AWT-EventQueue-1: headsup.draw
>
> T=1132 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
> T=1132 AWT-EventQueue-1: model.step
> T=1132 AWT-EventQueue-1: updateBackbuffer
> T=1132 AWT-EventQueue-1: repaint
> T=1132 AWT-EventQueue-1: update
> T=1132 AWT-EventQueue-1: paint
> T=1132 AWT-EventQueue-1: headsup.draw
>
> T=2133 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
> T=2133 AWT-EventQueue-1: model.step
> T=2133 AWT-EventQueue-1: updateBackbuffer
> T=2133 AWT-EventQueue-1: repaint
> T=2133 AWT-EventQueue-1: update
> T=2133 AWT-EventQueue-1: paint
> T=2133 AWT-EventQueue-1: headsup.draw
>
> T=3135 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
> T=3145 AWT-EventQueue-1: model.step
> T=3145 AWT-EventQueue-1: updateBackbuffer
> T=3165 AWT-EventQueue-1: repaint
> T=3165 AWT-EventQueue-1: update
> T=3165 AWT-EventQueue-1: paint
> T=3165 AWT-EventQueue-1: headsup.draw
> T=3205 AWT-EventQueue-1: update
> T=3205 AWT-EventQueue-1: paint
> T=3205 AWT-EventQueue-1: headsup.draw
> T=3245 AWT-EventQueue-1: update
> T=3245 AWT-EventQueue-1: paint
> T=3245 AWT-EventQueue-1: headsup.draw
> T=3285 AWT-EventQueue-1: update
> T=3285 AWT-EventQueue-1: paint
> T=3285 AWT-EventQueue-1: headsup.draw
> T=3325 AWT-EventQueue-1: update
> T=3325 AWT-EventQueue-1: paint
> T=3325 AWT-EventQueue-1: headsup.draw
> T=3365 AWT-EventQueue-1: update
> T=3365 AWT-EventQueue-1: paint
> T=3365 AWT-EventQueue-1: headsup.draw
> T=3405 AWT-EventQueue-1: update
> T=3405 AWT-EventQueue-1: paint
> T=3405 AWT-EventQueue-1: headsup.draw
> T=3445 AWT-EventQueue-1: update
> T=3445 AWT-EventQueue-1: paint
> T=3445 AWT-EventQueue-1: headsup.draw
> T=3495 AWT-EventQueue-1: update
> T=3495 AWT-EventQueue-1: paint
> T=3495 AWT-EventQueue-1: headsup.draw
> T=3535 AWT-EventQueue-1: update
> T=3535 AWT-EventQueue-1: paint
> T=3535 AWT-EventQueue-1: headsup.draw
> T=3575 AWT-EventQueue-1: update
> T=3575 AWT-EventQueue-1: paint
> T=3575 AWT-EventQueue-1: headsup.draw
> T=3615 AWT-EventQueue-1: update
> T=3615 AWT-EventQueue-1: paint
> T=3615 AWT-EventQueue-1: headsup.draw
> T=3655 AWT-EventQueue-1: update
> T=3655 AWT-EventQueue-1: paint
> T=3655 AWT-EventQueue-1: headsup.draw
> T=3705 AWT-EventQueue-1: update
> T=3705 AWT-EventQueue-1: paint
> T=3705 AWT-EventQueue-1: headsup.draw
> T=3745 AWT-EventQueue-1: update
> T=3745 AWT-EventQueue-1: paint
> T=3745 AWT-EventQueue-1: headsup.draw
> T=3786 AWT-EventQueue-1: update
> T=3786 AWT-EventQueue-1: paint
> T=3786 AWT-EventQueue-1: headsup.draw
> T=3826 AWT-EventQueue-1: update
> T=3826 AWT-EventQueue-1: paint
> T=3826 AWT-EventQueue-1: headsup.draw
> T=3866 AWT-EventQueue-1: update
> T=3866 AWT-EventQueue-1: paint
> T=3866 AWT-EventQueue-1: headsup.draw
> T=3906 AWT-EventQueue-1: update
> T=3906 AWT-EventQueue-1: paint
> T=3916 AWT-EventQueue-1: headsup.draw
> T=3956 AWT-EventQueue-1: update
> T=3956 AWT-EventQueue-1: paint
> T=3956 AWT-EventQueue-1: headsup.draw
> T=3996 AWT-EventQueue-1: update
> T=3996 AWT-EventQueue-1: paint
> T=3996 AWT-EventQueue-1: headsup.draw
> T=4036 AWT-EventQueue-1: update
> T=4036 AWT-EventQueue-1: paint
> T=4036 AWT-EventQueue-1: headsup.draw
> T=4076 AWT-EventQueue-1: update
> T=4076 AWT-EventQueue-1: paint
> T=4076 AWT-EventQueue-1: headsup.draw
> T=4126 AWT-EventQueue-1: update
> T=4126 AWT-EventQueue-1: paint
> T=4126 AWT-EventQueue-1: headsup.draw
>
> T=4136 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
> T=4136 AWT-EventQueue-1: model.step
> T=4136 AWT-EventQueue-1: updateBackbuffer
> T=4136 AWT-EventQueue-1: repaint
> T=4136 AWT-EventQueue-1: update
> T=4136 AWT-EventQueue-1: paint
> T=4136 AWT-EventQueue-1: headsup.draw
> T=4166 AWT-EventQueue-1: update
> T=4166 AWT-EventQueue-1: paint
> T=4166 AWT-EventQueue-1: headsup.draw
> T=4206 AWT-EventQueue-1: update
> T=4206 AWT-EventQueue-1: paint
> T=4206 AWT-EventQueue-1: headsup.draw
> T=4256 AWT-EventQueue-1: update
> T=4256 AWT-EventQueue-1: paint
> T=4256 AWT-EventQueue-1: headsup.draw
> T=4296 AWT-EventQueue-1: update
> T=4296 AWT-EventQueue-1: paint
> T=4296 AWT-EventQueue-1: headsup.draw
> T=4366 AWT-EventQueue-1: update
> T=4366 AWT-EventQueue-1: paint
> T=4366 AWT-EventQueue-1: headsup.draw
> T=4406 AWT-EventQueue-1: update
> T=4406 AWT-EventQueue-1: paint
> T=4406 AWT-EventQueue-1: headsup.draw
> T=4446 AWT-EventQueue-1: update
> T=4446 AWT-EventQueue-1: paint
> T=4446 AWT-EventQueue-1: headsup.draw
> T=4487 AWT-EventQueue-1: update
> T=4487 AWT-EventQueue-1: paint
> T=4487 AWT-EventQueue-1: headsup.draw
> T=4527 AWT-EventQueue-1: update
> T=4527 AWT-EventQueue-1: paint
> T=4527 AWT-EventQueue-1: headsup.draw
> T=4577 AWT-EventQueue-1: update
> T=4577 AWT-EventQueue-1: paint
> T=4577 AWT-EventQueue-1: headsup.draw
> T=4617 AWT-EventQueue-1: update
> T=4617 AWT-EventQueue-1: paint
> T=4617 AWT-EventQueue-1: headsup.draw
> T=4657 AWT-EventQueue-1: update
> T=4657 AWT-EventQueue-1: paint
> T=4657 AWT-EventQueue-1: headsup.draw
> T=4697 AWT-EventQueue-1: update
> T=4697 AWT-EventQueue-1: paint
> T=4697 AWT-EventQueue-1: headsup.draw
>
> As you can see, the mad-updating begins at T=3205 and continues then
> on. Note that the actionPerformed from the Swing-Timer is still
> functioning, and that the method that keeps getting called is update
> (which in turn calls paint, which call headsup.draw).
>
> /Olof
>
> On 8/25/05, Olof Bjarnason
wrote:
>> This is a very thourough answer. I will try to reply ...
>>
>> On 8/25/05, Jim Graham wrote:
>> > >> 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.
>> > >
>> > > OK, guess I misread the docs. Actually, I followed this tutorial to
>> > > begin with: http://www.dgp.toronto.edu/~mjmcguff/learn/java/
>> >
>> > either direction will work as long as you override both. Our docs
>> > show the guts in paint() and then update() redirecting to paint()
>> > since it reflects what would otherwise go on underneath the covers.
>> > Typically an animation program overrides paint() to start out with to
>> > draw a frame, because that is where a program should put its paint()
>> > code and that is where someone reading the code would go first to find
>> > the painting code. The override of update() is then added to stop the
>> > "erase to background color" flickering. When you look at it that way,
>> > it seems more logical to have the actual painting code in the paint()
>> > method, but both work as long as you override both.
>> I'm with you and I tried both, same result.
>>
>> >
>> > >> 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.
>> > > I'm using AWT I guess, no Swing. I'm trying to go for old-API in
>> > > order to make the game runnable on more computers. I compile for
>> > > 1.4.2, but I guess 1.4.2 has Swing so I could go for paintComponent,
>> > > but my feeling is I should use paint(), eg.the tutorial uses paint().
>> > > Comments?
>> >
>> > I don't see how the way you've overridden paint/update() can lead to
>> > the problem in and of itself. It would be an interesting experiment,
>> > but I wouldn't abandon your architecture to try to fix this.
>> I started "porting" my Applet to JApplet but it proved horrendously
>> errorprone (basically had to cut the file in three --- more work to
>> fix this than starting from scratch) so I am back at the
>> AWT/paint/update stage again.
>>
>> >
>> > >> 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?)
>> >
>> > This is a hard call. While I still need to think about the
>> > ramifications of what you've done with sending ActionEvents to
>> > yourself, simply using a Timer instead of rolling your own Thread
>> > would not change anything here if the action of the Timer was to send
>> > the ActionEvent.
>> I've tried both, same result. A potential error with my previous
>> "virtual-click-a-button" method was that it used the postEvent from a
>> custom thread. Given that the documents state that all AWT/Swing code
>> should execute using the invokeLater technique, this i not
>> recommended. Anyway, the Swing Timer didn't work either in my setting.
>>
>> >
>> > If you switched to periodic repaint() calls instead of sending an
>> > ActionEvent then it would mean that the calls to update() would happen
>> > directly instead of as a result of a frame update. You would either
>> > have to move the frame update code to the update() method, or you
>> > would have to have two timer events - one to update the frame, and
>> > another to call repaint - and the two would happen asynchronously.
>> >
>> > This points out a potential problem with the way you've written the
>> > code and could be the root cause of the flood of repaints. Are there
>> > ever any frames that take longer than 1 second to render? If so, then
>> > there is no inherent throttling of your ActionEvents to match the
>> > extended compute time. If, say, you have one frame update that takes
>> > 10 seconds to complete, then by the time it is done, there will be 10
>> > ActionEvents in the queue waiting to be processed. If those events
>> > take less time to process then you will run through all 10 of them at
>> > once and see 10 updates very quickly in a row which could look like
>> > what is happening to you. If it is much more likely to encounter
>> > frame updates that take longer than 1 second then the backup will be
>> > constantly increasing.
>> Simple answer: no. My updateBackbuffer code paints at most 64 tile
>> images sized 32x32 each, and actually even when the
>> non-stopping-updates is going on, there is no performance problem more
>> than the CPU getting up to like 10% (I'm sorry stated 90% earlier post
>> but that was a misreading must have been something else..). The way I
>> know there is mad-updating is via the console output (println) and
>> flickering (the headsup display widgets are flickering).
>>
>> >
>> > Instead of sending an ActionEvent every second which forces a frame
>> > update, you might want to have some way of creating back-pressure.
>> > Either:
>> >
>> > - have something in your frame update code which requests the
>> > subsequent frame when it is done and don't send another ActionEvent
>> > until it is requested - that guarantees a delay of N milliseconds
>> > "between" frames so if frames take longer than your delay, the
>> > ActionEvents don't accumulate. This is kind of hard to implement,
>> > though.
>> >
>> > - have your frame update code check the last time a frame was updated
>> > and if it was less than 1 second ago, skip this ActionEvent to catch up
>> > (another will come along in less than a second).
>> >
>> > - you can also look at the time-stamp of the ActionEvent and if it was
>> > sent more than 1 second ago, skip it in favor of one that you know
>> > will be coming along very soon.
>> >
>> > - have your frame update code increment "number of frames handled" and
>> > have the event sending code increment "number of frames requested" and
>> > if the requested count is too far ahead of the handled count (like
>> > more than 1 greater), skip a beat by not sending the ActionEvent this
>> > time.
>> >
>> > - use calls to update to trigger your frame updates and use "timed
>> > repaint" events which coalesce:
>> >
>> > Timer thread {
>> > loop {
>> > sleep(1000);
>> > repaint(10); // Will coalesce with other
>> > repaint(ms) calls }
>> > }
>> >
>> > update(Graphics g) {
>> > updateframe();
>> > paint(g);
>> > }
>> >
>> > paint(Graphics g) {
>> > g.drawImage(backbuffer);
>> > drawheadsup(g);
>> > }
>> >
>> > Note that calls to repaint() with no delay will be queued and result in
>> > calls to update() on a 1 for 1 basis so you could end up with the same
>> > backlog, but calls to repaint() with a delay (as above) will be
>> > coalesced with each other.
>> >
>> > >> - 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.
>> >
>> > That will help keep the frame update code from getting too far behind
>> > the event sending thread...
>> >
>> > ...jim
>> >
>> >
>> Thanks for your time,
>>
>> /Olof
>>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

Here it is:

public void draw(Graphics g) {
Debug.println("headsup.draw");
g.setColor(Color.GREEN);
int topline = gfxState.yoffset + 1;
int leftline = gfxState.xoffset + 1;
int rightline = gfxState.xoffset - 1 +
gfxState.viewTileWidth*gfxState.tileSize;
int bottomline = gfxState.yoffset - 1 +
gfxState.viewTileHeight*gfxState.tileSize;
int arrowSize = gfxState.tileSize / 4;
int centerH = gfxState.appletWidth / 2;
int centerV = gfxState.appletHeight / 2;
if(northArrow) {
g.drawLine(centerH, topline, centerH-arrowSize, topline+arrowSize);
g.drawLine(centerH, topline, centerH+arrowSize, topline+arrowSize);
}
if(eastArrow) {
g.drawLine(rightline, centerV, rightline-arrowSize, centerV-arrowSize);
g.drawLine(rightline, centerV, rightline-arrowSize, centerV+arrowSize);
}
if(southArrow) {
g.drawLine(centerH, bottomline, centerH-arrowSize, bottomline-arrowSize);
g.drawLine(centerH, bottomline, centerH+arrowSize, bottomline-arrowSize);
}
if(westArrow) {
g.drawLine(leftline, centerV, leftline+arrowSize, centerV-arrowSize);
g.drawLine(leftline, centerV, leftline+arrowSize, centerV+arrowSize);
}
if(cursor) {
g.setColor(Color.YELLOW);
g.drawRect(gfxState.xoffset+this.cursorx*gfxState.tileSize,
gfxState.yoffset+this.cursory*gfxState.tileSize, gfxState.tileSize-1,
gfxState.tileSize-1);
g.drawRect(gfxState.xoffset+this.cursorx*gfxState.tileSize+gfxState.tileSize/8,
gfxState.yoffset+this.cursory*gfxState.tileSize+gfxState.tileSize/8,
6*gfxState.tileSize/8-1, 6*gfxState.tileSize/8-1);
}
}

On 8/25/05, Jim Graham wrote:
> This is hard to tell without seeing the code in the headsup.draw method...
>
> ...jim
>
> --On Thursday, August 25, 2005 10:19 PM +0200 Olof Bjarnason
>
wrote:
>
> > OK I've done some debug-printing for you to get a feeling of the
> > behaviour. I use this debug-println:
> >
> > public static void println(String str) {
> > long millis = System.currentTimeMillis() - startMillis;
> > String threadName = Thread.currentThread().getName();
> > System.out.println("T="+millis+"\t"+threadName + ": " + str);
> > }
> >
> > ... which give me quite a lot of information. This is the printout
> > from a typical 5-second run:
> > (WARNING: many lines below!)
> >
> > (ms) (name of thread) (message)
> > T=0 thread applet-terraformer.TerraformerApplet.class: Setting up model.
> > T=0 thread applet-terraformer.TerraformerApplet.class: Setting up
> > graphics fundaments.
> > T=0 thread applet-terraformer.TerraformerApplet.class: Loading resources.
> > T=10 thread applet-terraformer.TerraformerApplet.class: Downloading
> > images. T=120 thread applet-terraformer.TerraformerApplet.class: Creating
> > backbuffer. T=130 thread applet-terraformer.TerraformerApplet.class:
> > Creating headsup display.
> > T=130 thread applet-terraformer.TerraformerApplet.class: Setting up
> > rendering state.
> > T=130 AWT-EventQueue-1: Accepting keyboard input once focused.
> > T=130 AWT-EventQueue-1: Doing first background render.
> > T=130 AWT-EventQueue-1: updateBackbuffer
> > T=130 AWT-EventQueue-1: repaint
> > T=130 AWT-EventQueue-1: paint
> > T=140 AWT-EventQueue-1: headsup.draw
> >
> > T=1132 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
> > T=1132 AWT-EventQueue-1: model.step
> > T=1132 AWT-EventQueue-1: updateBackbuffer
> > T=1132 AWT-EventQueue-1: repaint
> > T=1132 AWT-EventQueue-1: update
> > T=1132 AWT-EventQueue-1: paint
> > T=1132 AWT-EventQueue-1: headsup.draw
> >
> > T=2133 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
> > T=2133 AWT-EventQueue-1: model.step
> > T=2133 AWT-EventQueue-1: updateBackbuffer
> > T=2133 AWT-EventQueue-1: repaint
> > T=2133 AWT-EventQueue-1: update
> > T=2133 AWT-EventQueue-1: paint
> > T=2133 AWT-EventQueue-1: headsup.draw
> >
> > T=3135 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
> > T=3145 AWT-EventQueue-1: model.step
> > T=3145 AWT-EventQueue-1: updateBackbuffer
> > T=3165 AWT-EventQueue-1: repaint
> > T=3165 AWT-EventQueue-1: update
> > T=3165 AWT-EventQueue-1: paint
> > T=3165 AWT-EventQueue-1: headsup.draw
> > T=3205 AWT-EventQueue-1: update
> > T=3205 AWT-EventQueue-1: paint
> > T=3205 AWT-EventQueue-1: headsup.draw
> > T=3245 AWT-EventQueue-1: update
> > T=3245 AWT-EventQueue-1: paint
> > T=3245 AWT-EventQueue-1: headsup.draw
> > T=3285 AWT-EventQueue-1: update
> > T=3285 AWT-EventQueue-1: paint
> > T=3285 AWT-EventQueue-1: headsup.draw
> > T=3325 AWT-EventQueue-1: update
> > T=3325 AWT-EventQueue-1: paint
> > T=3325 AWT-EventQueue-1: headsup.draw
> > T=3365 AWT-EventQueue-1: update
> > T=3365 AWT-EventQueue-1: paint
> > T=3365 AWT-EventQueue-1: headsup.draw
> > T=3405 AWT-EventQueue-1: update
> > T=3405 AWT-EventQueue-1: paint
> > T=3405 AWT-EventQueue-1: headsup.draw
> > T=3445 AWT-EventQueue-1: update
> > T=3445 AWT-EventQueue-1: paint
> > T=3445 AWT-EventQueue-1: headsup.draw
> > T=3495 AWT-EventQueue-1: update
> > T=3495 AWT-EventQueue-1: paint
> > T=3495 AWT-EventQueue-1: headsup.draw
> > T=3535 AWT-EventQueue-1: update
> > T=3535 AWT-EventQueue-1: paint
> > T=3535 AWT-EventQueue-1: headsup.draw
> > T=3575 AWT-EventQueue-1: update
> > T=3575 AWT-EventQueue-1: paint
> > T=3575 AWT-EventQueue-1: headsup.draw
> > T=3615 AWT-EventQueue-1: update
> > T=3615 AWT-EventQueue-1: paint
> > T=3615 AWT-EventQueue-1: headsup.draw
> > T=3655 AWT-EventQueue-1: update
> > T=3655 AWT-EventQueue-1: paint
> > T=3655 AWT-EventQueue-1: headsup.draw
> > T=3705 AWT-EventQueue-1: update
> > T=3705 AWT-EventQueue-1: paint
> > T=3705 AWT-EventQueue-1: headsup.draw
> > T=3745 AWT-EventQueue-1: update
> > T=3745 AWT-EventQueue-1: paint
> > T=3745 AWT-EventQueue-1: headsup.draw
> > T=3786 AWT-EventQueue-1: update
> > T=3786 AWT-EventQueue-1: paint
> > T=3786 AWT-EventQueue-1: headsup.draw
> > T=3826 AWT-EventQueue-1: update
> > T=3826 AWT-EventQueue-1: paint
> > T=3826 AWT-EventQueue-1: headsup.draw
> > T=3866 AWT-EventQueue-1: update
> > T=3866 AWT-EventQueue-1: paint
> > T=3866 AWT-EventQueue-1: headsup.draw
> > T=3906 AWT-EventQueue-1: update
> > T=3906 AWT-EventQueue-1: paint
> > T=3916 AWT-EventQueue-1: headsup.draw
> > T=3956 AWT-EventQueue-1: update
> > T=3956 AWT-EventQueue-1: paint
> > T=3956 AWT-EventQueue-1: headsup.draw
> > T=3996 AWT-EventQueue-1: update
> > T=3996 AWT-EventQueue-1: paint
> > T=3996 AWT-EventQueue-1: headsup.draw
> > T=4036 AWT-EventQueue-1: update
> > T=4036 AWT-EventQueue-1: paint
> > T=4036 AWT-EventQueue-1: headsup.draw
> > T=4076 AWT-EventQueue-1: update
> > T=4076 AWT-EventQueue-1: paint
> > T=4076 AWT-EventQueue-1: headsup.draw
> > T=4126 AWT-EventQueue-1: update
> > T=4126 AWT-EventQueue-1: paint
> > T=4126 AWT-EventQueue-1: headsup.draw
> >
> > T=4136 AWT-EventQueue-1: actionPerformed (by Swing-Timer)
> > T=4136 AWT-EventQueue-1: model.step
> > T=4136 AWT-EventQueue-1: updateBackbuffer
> > T=4136 AWT-EventQueue-1: repaint
> > T=4136 AWT-EventQueue-1: update
> > T=4136 AWT-EventQueue-1: paint
> > T=4136 AWT-EventQueue-1: headsup.draw
> > T=4166 AWT-EventQueue-1: update
> > T=4166 AWT-EventQueue-1: paint
> > T=4166 AWT-EventQueue-1: headsup.draw
> > T=4206 AWT-EventQueue-1: update
> > T=4206 AWT-EventQueue-1: paint
> > T=4206 AWT-EventQueue-1: headsup.draw
> > T=4256 AWT-EventQueue-1: update
> > T=4256 AWT-EventQueue-1: paint
> > T=4256 AWT-EventQueue-1: headsup.draw
> > T=4296 AWT-EventQueue-1: update
> > T=4296 AWT-EventQueue-1: paint
> > T=4296 AWT-EventQueue-1: headsup.draw
> > T=4366 AWT-EventQueue-1: update
> > T=4366 AWT-EventQueue-1: paint
> > T=4366 AWT-EventQueue-1: headsup.draw
> > T=4406 AWT-EventQueue-1: update
> > T=4406 AWT-EventQueue-1: paint
> > T=4406 AWT-EventQueue-1: headsup.draw
> > T=4446 AWT-EventQueue-1: update
> > T=4446 AWT-EventQueue-1: paint
> > T=4446 AWT-EventQueue-1: headsup.draw
> > T=4487 AWT-EventQueue-1: update
> > T=4487 AWT-EventQueue-1: paint
> > T=4487 AWT-EventQueue-1: headsup.draw
> > T=4527 AWT-EventQueue-1: update
> > T=4527 AWT-EventQueue-1: paint
> > T=4527 AWT-EventQueue-1: headsup.draw
> > T=4577 AWT-EventQueue-1: update
> > T=4577 AWT-EventQueue-1: paint
> > T=4577 AWT-EventQueue-1: headsup.draw
> > T=4617 AWT-EventQueue-1: update
> > T=4617 AWT-EventQueue-1: paint
> > T=4617 AWT-EventQueue-1: headsup.draw
> > T=4657 AWT-EventQueue-1: update
> > T=4657 AWT-EventQueue-1: paint
> > T=4657 AWT-EventQueue-1: headsup.draw
> > T=4697 AWT-EventQueue-1: update
> > T=4697 AWT-EventQueue-1: paint
> > T=4697 AWT-EventQueue-1: headsup.draw
> >
> > As you can see, the mad-updating begins at T=3205 and continues then
> > on. Note that the actionPerformed from the Swing-Timer is still
> > functioning, and that the method that keeps getting called is update
> > (which in turn calls paint, which call headsup.draw).
> >
> > /Olof
> >
> > On 8/25/05, Olof Bjarnason
wrote:
> >> This is a very thourough answer. I will try to reply ...
> >>
> >> On 8/25/05, Jim Graham wrote:
> >> > >> 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.
> >> > >
> >> > > OK, guess I misread the docs. Actually, I followed this tutorial to
> >> > > begin with: http://www.dgp.toronto.edu/~mjmcguff/learn/java/
> >> >
> >> > either direction will work as long as you override both. Our docs
> >> > show the guts in paint() and then update() redirecting to paint()
> >> > since it reflects what would otherwise go on underneath the covers.
> >> > Typically an animation program overrides paint() to start out with to
> >> > draw a frame, because that is where a program should put its paint()
> >> > code and that is where someone reading the code would go first to find
> >> > the painting code. The override of update() is then added to stop the
> >> > "erase to background color" flickering. When you look at it that way,
> >> > it seems more logical to have the actual painting code in the paint()
> >> > method, but both work as long as you override both.
> >> I'm with you and I tried both, same result.
> >>
> >> >
> >> > >> 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.
> >> > > I'm using AWT I guess, no Swing. I'm trying to go for old-API in
> >> > > order to make the game runnable on more computers. I compile for
> >> > > 1.4.2, but I guess 1.4.2 has Swing so I could go for paintComponent,
> >> > > but my feeling is I should use paint(), eg.the tutorial uses paint().
> >> > > Comments?
> >> >
> >> > I don't see how the way you've overridden paint/update() can lead to
> >> > the problem in and of itself. It would be an interesting experiment,
> >> > but I wouldn't abandon your architecture to try to fix this.
> >> I started "porting" my Applet to JApplet but it proved horrendously
> >> errorprone (basically had to cut the file in three --- more work to
> >> fix this than starting from scratch) so I am back at the
> >> AWT/paint/update stage again.
> >>
> >> >
> >> > >> 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?)
> >> >
> >> > This is a hard call. While I still need to think about the
> >> > ramifications of what you've done with sending ActionEvents to
> >> > yourself, simply using a Timer instead of rolling your own Thread
> >> > would not change anything here if the action of the Timer was to send
> >> > the ActionEvent.
> >> I've tried both, same result. A potential error with my previous
> >> "virtual-click-a-button" method was that it used the postEvent from a
> >> custom thread. Given that the documents state that all AWT/Swing code
> >> should execute using the invokeLater technique, this i not
> >> recommended. Anyway, the Swing Timer didn't work either in my setting.
> >>
> >> >
> >> > If you switched to periodic repaint() calls instead of sending an
> >> > ActionEvent then it would mean that the calls to update() would happen
> >> > directly instead of as a result of a frame update. You would either
> >> > have to move the frame update code to the update() method, or you
> >> > would have to have two timer events - one to update the frame, and
> >> > another to call repaint - and the two would happen asynchronously.
> >> >
> >> > This points out a potential problem with the way you've written the
> >> > code and could be the root cause of the flood of repaints. Are there
> >> > ever any frames that take longer than 1 second to render? If so, then
> >> > there is no inherent throttling of your ActionEvents to match the
> >> > extended compute time. If, say, you have one frame update that takes
> >> > 10 seconds to complete, then by the time it is done, there will be 10
> >> > ActionEvents in the queue waiting to be processed. If those events
> >> > take less time to process then you will run through all 10 of them at
> >> > once and see 10 updates very quickly in a row which could look like
> >> > what is happening to you. If it is much more likely to encounter
> >> > frame updates that take longer than 1 second then the backup will be
> >> > constantly increasing.
> >> Simple answer: no. My updateBackbuffer code paints at most 64 tile
> >> images sized 32x32 each, and actually even when the
> >> non-stopping-updates is going on, there is no performance problem more
> >> than the CPU getting up to like 10% (I'm sorry stated 90% earlier post
> >> but that was a misreading must have been something else..). The way I
> >> know there is mad-updating is via the console output (println) and
> >> flickering (the headsup display widgets are flickering).
> >>
> >> >
> >> > Instead of sending an ActionEvent every second which forces a frame
> >> > update, you might want to have some way of creating back-pressure.
> >> > Either:
> >> >
> >> > - have something in your frame update code which requests the
> >> > subsequent frame when it is done and don't send another ActionEvent
> >> > until it is requested - that guarantees a delay of N milliseconds
> >> > "between" frames so if frames take longer than your delay, the
> >> > ActionEvents don't accumulate. This is kind of hard to implement,
> >> > though.
> >> >
> >> > - have your frame update code check the last time a frame was updated
> >> > and if it was less than 1 second ago, skip this ActionEvent to catch up
> >> > (another will come along in less than a second).
> >> >
> >> > - you can also look at the time-stamp of the ActionEvent and if it was
> >> > sent more than 1 second ago, skip it in favor of one that you know
> >> > will be coming along very soon.
> >> >
> >> > - have your frame update code increment "number of frames handled" and
> >> > have the event sending code increment "number of frames requested" and
> >> > if the requested count is too far ahead of the handled count (like
> >> > more than 1 greater), skip a beat by not sending the ActionEvent this
> >> > time.
> >> >
> >> > - use calls to update to trigger your frame updates and use "timed
> >> > repaint" events which coalesce:
> >> >
> >> > Timer thread {
> >> > loop {
> >> > sleep(1000);
> >> > repaint(10); // Will coalesce with other
> >> > repaint(ms) calls }
> >> > }
> >> >
> >> > update(Graphics g) {
> >> > updateframe();
> >> > paint(g);
> >> > }
> >> >
> >> > paint(Graphics g) {
> >> > g.drawImage(backbuffer);
> >> > drawheadsup(g);
> >> > }
> >> >
> >> > Note that calls to repaint() with no delay will be queued and result in
> >> > calls to update() on a 1 for 1 basis so you could end up with the same
> >> > backlog, but calls to repaint() with a delay (as above) will be
> >> > coalesced with each other.
> >> >
> >> > >> - 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.
> >> >
> >> > That will help keep the frame update code from getting too far behind
> >> > the event sending thread...
> >> >
> >> > ...jim
> >> >
> >> >
> >> Thanks for your time,
> >>
> >> /Olof
> >>
>
>
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Jim Graham

> 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);
> }
>
> 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.

Are you calling repaint() from anywhere other than your frame update?

Note that using "this" as the last parameter of g.drawImage() can lead to
calls to repaint() since the default implementation of the ImageObserver in
Component executes a call to repaint whenever more of the image is loaded
from its source. However, this only happens for images loaded from a file
or network connection, not images created with "createImage(w, h)" or "new
BufferedImage()" (basically any image that you can render into which
eliminates backbuffers) since those images are not loaded from a source
image stream.

> 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.

Have you tried it with 1.5? Or one of the pre-release builds of 1.6?

What happens right before the trigger? You could try overriding repaint()
to see where it is coming from, but it is hard to get that information back
out of the applet. You could see if the calls are going to paint() or
update() by doing something like:

update(Graphics g) {
render(g, Color.blue);
}

paint(Graphics g) {
render(g, Color.red);
}

render(Graphics g, Color trackcolor) {
// the code from your current update() method
// followed by:

g.setColor(trackcolor);
g.fillRect(0, 0, 10, 10);
}

Depending on the color of the square in the upper left you would know if
this was the result of a call to update() (which means it came from a call
to repaint() at some point) or if it was a call directly to paint() (which
means it was handling some perceived "damage" to the window)...

...jim

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

I'm using the Java Console and System.out.println() for debugging in Firefox.

On 8/25/05, Jim Graham wrote:
> > 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);
> > }
> >
> > 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.
>
> Are you calling repaint() from anywhere other than your frame update?

See one of my previous mails in this thread; I've tried removing ALL
repaints() from my code without any change in behaviour.

>
> Note that using "this" as the last parameter of g.drawImage() can lead to
> calls to repaint() since the default implementation of the ImageObserver in
> Component executes a call to repaint whenever more of the image is loaded
> from its source. However, this only happens for images loaded from a file
> or network connection, not images created with "createImage(w, h)" or "new
> BufferedImage()" (basically any image that you can render into which
> eliminates backbuffers) since those images are not loaded from a source
> image stream.
I'm using a MediaTracker to ensure that all images has been downloaded
in the init() method.

>
> > 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.
>
> Have you tried it with 1.5? Or one of the pre-release builds of 1.6?

I've tried 1.4.2 and 1.5.02, same behaviour.

> What happens right before the trigger? You could try overriding repaint()
repaint() is not getting called excessively. It is only update() that
gets called all the time. I know this since I tried this:

public void repaint() {
System.out.println("repaint");
super.repaint();
}

.. without "repaint" being printed every time "update" was printed
(did the same thing for update() )

> to see where it is coming from, but it is hard to get that information back
> out of the applet. You could see if the calls are going to paint() or
> update() by doing something like:
>
> update(Graphics g) {
> render(g, Color.blue);
> }
>
> paint(Graphics g) {
> render(g, Color.red);
> }
>
> render(Graphics g, Color trackcolor) {
> // the code from your current update() method
> // followed by:
>
> g.setColor(trackcolor);
> g.fillRect(0, 0, 10, 10);
> }
>
> Depending on the color of the square in the upper left you would know if
> this was the result of a call to update() (which means it came from a call
> to repaint() at some point) or if it was a call directly to paint() (which
> means it was handling some perceived "damage" to the window)...

I am certain it is update() that is getting called excessively.

Thanks for you ideas..

/Olof

>
> ...jim
>
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

OK since I've got you attention, please give me an educated answer to this:

Should I use Swing exclusively for a web page game? Which version of
the JRE Firefox-plugin is stable for end-users if I decide to use
Swing instead of just ground-plate AWT?

Thanks for your ideas,

/Olof

On 8/25/05, Olof Bjarnason
wrote:
> I'm using the Java Console and System.out.println() for debugging in Firefox.
>
> On 8/25/05, Jim Graham wrote:
> > > 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);
> > > }
> > >
> > > 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.
> >
> > Are you calling repaint() from anywhere other than your frame update?
>
> See one of my previous mails in this thread; I've tried removing ALL
> repaints() from my code without any change in behaviour.
>
> >
> > Note that using "this" as the last parameter of g.drawImage() can lead to
> > calls to repaint() since the default implementation of the ImageObserver in
> > Component executes a call to repaint whenever more of the image is loaded
> > from its source. However, this only happens for images loaded from a file
> > or network connection, not images created with "createImage(w, h)" or "new
> > BufferedImage()" (basically any image that you can render into which
> > eliminates backbuffers) since those images are not loaded from a source
> > image stream.
> I'm using a MediaTracker to ensure that all images has been downloaded
> in the init() method.
>
> >
> > > 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.
> >
> > Have you tried it with 1.5? Or one of the pre-release builds of 1.6?
>
> I've tried 1.4.2 and 1.5.02, same behaviour.
>
> > What happens right before the trigger? You could try overriding repaint()
> repaint() is not getting called excessively. It is only update() that
> gets called all the time. I know this since I tried this:
>
> public void repaint() {
> System.out.println("repaint");
> super.repaint();
> }
>
> .. without "repaint" being printed every time "update" was printed
> (did the same thing for update() )
>
>
> > to see where it is coming from, but it is hard to get that information back
> > out of the applet. You could see if the calls are going to paint() or
> > update() by doing something like:
> >
> > update(Graphics g) {
> > render(g, Color.blue);
> > }
> >
> > paint(Graphics g) {
> > render(g, Color.red);
> > }
> >
> > render(Graphics g, Color trackcolor) {
> > // the code from your current update() method
> > // followed by:
> >
> > g.setColor(trackcolor);
> > g.fillRect(0, 0, 10, 10);
> > }
> >
> > Depending on the color of the square in the upper left you would know if
> > this was the result of a call to update() (which means it came from a call
> > to repaint() at some point) or if it was a call directly to paint() (which
> > means it was handling some perceived "damage" to the window)...
>
> I am certain it is update() that is getting called excessively.
>
> Thanks for you ideas..
>
> /Olof
>
> >
> > ...jim
> >
> >
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Jim Graham

Hi Olof,

There is no hard requirement to use Swing. It does provide a number of
features, such as automatic double buffering and Timers, which could save
you some coding and debugging time, but it is also possible to roll your
own as you have already done. Swing also provides a lot of features that
you probably don't need in a web page game, though they shouldn't get in
your way or hurt you.

AWT is a lower level API, but still reasonably high level in the grand
scheme of things (i.e. all of the GUI toolkits out there), so it is equally
useful for your purposes...

...jim

--On Thursday, August 25, 2005 8:37 PM +0200 Olof Bjarnason

wrote:
> OK since I've got you attention, please give me an educated answer to
> this:
>
> Should I use Swing exclusively for a web page game? Which version of
> the JRE Firefox-plugin is stable for end-users if I decide to use
> Swing instead of just ground-plate AWT?
>
> Thanks for your ideas,
>
> /Olof

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

Is there any particular part of my source code you want me to post?
Posting the whole project seems a bit too much for a mailing list...

Thanks for your help,

/Olof

On 8/25/05, Jim Graham wrote:
> Hi Olof,
>
> There is no hard requirement to use Swing. It does provide a number of
> features, such as automatic double buffering and Timers, which could save
> you some coding and debugging time, but it is also possible to roll your
> own as you have already done. Swing also provides a lot of features that
> you probably don't need in a web page game, though they shouldn't get in
> your way or hurt you.
>
> AWT is a lower level API, but still reasonably high level in the grand
> scheme of things (i.e. all of the GUI toolkits out there), so it is equally
> useful for your purposes...
>
> ...jim
>
> --On Thursday, August 25, 2005 8:37 PM +0200 Olof Bjarnason
>
wrote:
> > OK since I've got you attention, please give me an educated answer to
> > this:
> >
> > Should I use Swing exclusively for a web page game? Which version of
> > the JRE Firefox-plugin is stable for end-users if I decide to use
> > Swing instead of just ground-plate AWT?
> >
> > Thanks for your ideas,
> >
> > /Olof
>
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Jim Graham

We've probably exceeded the interest level of those here. The best
thing at this stage would be to try to boil the test case down to the
smallest case that still reproduces it (i.e. make a copy and start
deleting/stubbing code while the problem still persists, etc.) and
then send it to just me and I'll take a look at it off-line...

...jim

--On Thursday, August 25, 2005 11:39 PM +0200 Olof Bjarnason

wrote:

> Is there any particular part of my source code you want me to post?
> Posting the whole project seems a bit too much for a mailing list...
>
> Thanks for your help,
>
> /Olof
>
> On 8/25/05, Jim Graham wrote:
>> Hi Olof,
>>
>> There is no hard requirement to use Swing. It does provide a number of
>> features, such as automatic double buffering and Timers, which could save
>> you some coding and debugging time, but it is also possible to roll your
>> own as you have already done. Swing also provides a lot of features that
>> you probably don't need in a web page game, though they shouldn't get in
>> your way or hurt you.
>>
>> AWT is a lower level API, but still reasonably high level in the grand
>> scheme of things (i.e. all of the GUI toolkits out there), so it is
>> equally useful for your purposes...
>>
>> ...jim
>>
>> --On Thursday, August 25, 2005 8:37 PM +0200 Olof Bjarnason
>>
wrote:
>> > OK since I've got you attention, please give me an educated answer to
>> > this:
>> >
>> > Should I use Swing exclusively for a web page game? Which version of
>> > the JRE Firefox-plugin is stable for end-users if I decide to use
>> > Swing instead of just ground-plate AWT?
>> >
>> > Thanks for your ideas,
>> >
>> > /Olof
>>
>>
>
> =========================================================================
> == To unsubscribe, send email to listserv@java.sun.com and include in the
> body of the message "signoff JAVA2D-INTEREST". For general help, send
> email to listserv@java.sun.com and include in the body of the message
> "help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

Hi again java2d-list and Jim especially,

OK I've tried to boil down the project as Jim suggested. At this
stage, if I remove anything I can't seem to reproduce the problem. If
you have interest enough to check it out, I am very thankful.

First off, the Applet which shows the counts of updates, repaints and
paints. Note after some seconds the update count and the paint count
"runs away" - the "mad-update" behaviour:

http://olofbjarnason.se/Terraformer/bin/Terraformer.html

I've generated a javadoc tree, source code included:

http://olofbjarnason.se/Terraformer/doc/index.html

.. and also here is the source with resources:

http://olofbjarnason.se/Terraformer/Terraformer.zip
(compile: javac *.java in terraformer directory, run with Terraformer.html)

Short project briefing:

The Debug and GraphicsState classes are very small and have no
graphics/AWT code at all. The Model class is "purely logical" - the
simulation - it is quite big just skip checking it - it has no AWT
code either. The important classes I should guess are
TerraformerApplet and ResourceManager which do the AWT/graphics stuff,
alone. ResourceManager uses a MediaTracker to load the images
synchronously.

Cya and thanks for you help,

/Olof

On 8/26/05, Jim Graham wrote:
> We've probably exceeded the interest level of those here. The best
> thing at this stage would be to try to boil the test case down to the
> smallest case that still reproduces it (i.e. make a copy and start
> deleting/stubbing code while the problem still persists, etc.) and
> then send it to just me and I'll take a look at it off-line...
>
> ...jim
>
>
> --On Thursday, August 25, 2005 11:39 PM +0200 Olof Bjarnason
>
wrote:
>
> > Is there any particular part of my source code you want me to post?
> > Posting the whole project seems a bit too much for a mailing list...
> >
> > Thanks for your help,
> >
> > /Olof
> >
> > On 8/25/05, Jim Graham wrote:
> >> Hi Olof,
> >>
> >> There is no hard requirement to use Swing. It does provide a number of
> >> features, such as automatic double buffering and Timers, which could save
> >> you some coding and debugging time, but it is also possible to roll your
> >> own as you have already done. Swing also provides a lot of features that
> >> you probably don't need in a web page game, though they shouldn't get in
> >> your way or hurt you.
> >>
> >> AWT is a lower level API, but still reasonably high level in the grand
> >> scheme of things (i.e. all of the GUI toolkits out there), so it is
> >> equally useful for your purposes...
> >>
> >> ...jim
> >>
> >> --On Thursday, August 25, 2005 8:37 PM +0200 Olof Bjarnason
> >>
wrote:
> >> > OK since I've got you attention, please give me an educated answer to
> >> > this:
> >> >
> >> > Should I use Swing exclusively for a web page game? Which version of
> >> > the JRE Firefox-plugin is stable for end-users if I decide to use
> >> > Swing instead of just ground-plate AWT?
> >> >
> >> > Thanks for your ideas,
> >> >
> >> > /Olof
> >>
> >>
> >
> > =========================================================================
> > == To unsubscribe, send email to listserv@java.sun.com and include in the
> > body of the message "signoff JAVA2D-INTEREST". For general help, send
> > email to listserv@java.sun.com and include in the body of the message
> > "help".
>
>
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Jim Graham

Several of your images have tags which identify them as animated images
even though they only have one frame defined. All of them have a "graphics
extension block" listing a non-zero "animation frame delay" which implies
that they are multi-frame GIF images with a delay between frames (40ms in
most cases).

wall_8.gif also has a NETSCAPE2.0 "loop count" tag defined which is another
indicator that the image is animated.

The repaints are our mechanism for getting you to render everything again
"when the next animated frame in the image you drew" is ready - it is a
result of the default implementation of the ImageObserver interface in
"this" - the parameter you give to us as your ImageObserver.

I would edit your images again and turn off all options related to anything
to do with animation or multi-frame images - inter-frame delays, loop
counts, etc. As an alternative you can convert them to PNG images which
should work on 1.4 and later runtimes (actually as far back as 1.2 I
believe)...

...jim

--On Monday, August 29, 2005 2:05 PM +0200 Olof Bjarnason

wrote:

> Hi again java2d-list and Jim especially,
>
> OK I've tried to boil down the project as Jim suggested. At this
> stage, if I remove anything I can't seem to reproduce the problem. If
> you have interest enough to check it out, I am very thankful.
>
> First off, the Applet which shows the counts of updates, repaints and
> paints. Note after some seconds the update count and the paint count
> "runs away" - the "mad-update" behaviour:
>
> http://olofbjarnason.se/Terraformer/bin/Terraformer.html
>
> I've generated a javadoc tree, source code included:
>
> http://olofbjarnason.se/Terraformer/doc/index.html
>
> .. and also here is the source with resources:
>
> http://olofbjarnason.se/Terraformer/Terraformer.zip
> (compile: javac *.java in terraformer directory, run with
> Terraformer.html)
>
> Short project briefing:
>
> The Debug and GraphicsState classes are very small and have no
> graphics/AWT code at all. The Model class is "purely logical" - the
> simulation - it is quite big just skip checking it - it has no AWT
> code either. The important classes I should guess are
> TerraformerApplet and ResourceManager which do the AWT/graphics stuff,
> alone. ResourceManager uses a MediaTracker to load the images
> synchronously.
>
> Cya and thanks for you help,
>
> /Olof
>
>
> On 8/26/05, Jim Graham wrote:
>> We've probably exceeded the interest level of those here. The best
>> thing at this stage would be to try to boil the test case down to the
>> smallest case that still reproduces it (i.e. make a copy and start
>> deleting/stubbing code while the problem still persists, etc.) and
>> then send it to just me and I'll take a look at it off-line...
>>
>> ...jim
>>
>>
>> --On Thursday, August 25, 2005 11:39 PM +0200 Olof Bjarnason
>>
wrote:
>>
>> > Is there any particular part of my source code you want me to post?
>> > Posting the whole project seems a bit too much for a mailing list...
>> >
>> > Thanks for your help,
>> >
>> > /Olof
>> >
>> > On 8/25/05, Jim Graham wrote:
>> >> Hi Olof,
>> >>
>> >> There is no hard requirement to use Swing. It does provide a number
>> >> of features, such as automatic double buffering and Timers, which
>> >> could save you some coding and debugging time, but it is also
>> >> possible to roll your own as you have already done. Swing also
>> >> provides a lot of features that you probably don't need in a web page
>> >> game, though they shouldn't get in your way or hurt you.
>> >>
>> >> AWT is a lower level API, but still reasonably high level in the grand
>> >> scheme of things (i.e. all of the GUI toolkits out there), so it is
>> >> equally useful for your purposes...
>> >>
>> >> ...jim
>> >>
>> >> --On Thursday, August 25, 2005 8:37 PM +0200 Olof Bjarnason
>> >>
wrote:
>> >> > OK since I've got you attention, please give me an educated answer
>> >> > to this:
>> >> >
>> >> > Should I use Swing exclusively for a web page game? Which version of
>> >> > the JRE Firefox-plugin is stable for end-users if I decide to use
>> >> > Swing instead of just ground-plate AWT?
>> >> >
>> >> > Thanks for your ideas,
>> >> >
>> >> > /Olof
>> >>
>> >>
>> >
>> > ======================================================================
>> > === == To unsubscribe, send email to listserv@java.sun.com and include
>> > in the body of the message "signoff JAVA2D-INTEREST". For general
>> > help, send email to listserv@java.sun.com and include in the body of
>> > the message "help".
>>
>>
>>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

I converted the .gif:s to .png:s (the Exorcist utility! nice try it)
and judging by a first "feel run" of the program, the problem
dissappered! :)

Jim: I am very grateful to you. The paint program I use mention only
one frame, but probably inserts some "waste info" in the gif:s anyway.
I think I will mail them to ask them to let the user have more power
over exactly what info goes into the gifs, or else just start using
png instead.

wall_8.gif was strange - dunno why it differed from the others. Used
same program to save it. Actually, I had observed some "anomalities"
during program execution with wall 8 - sometimes it just didn't show
at all - guess I got the explanation now.

Once again, thank you very much, now I can finish the game and I've
also learned alot..
I'm planning on making the game a "home page game" so maybe I'll keep
you posted on the progress here..

cya,

/Olof

On 8/29/05, Jim Graham wrote:
> Several of your images have tags which identify them as animated images
> even though they only have one frame defined. All of them have a "graphics
> extension block" listing a non-zero "animation frame delay" which implies
> that they are multi-frame GIF images with a delay between frames (40ms in
> most cases).
>
> wall_8.gif also has a NETSCAPE2.0 "loop count" tag defined which is another
> indicator that the image is animated.
>
> The repaints are our mechanism for getting you to render everything again
> "when the next animated frame in the image you drew" is ready - it is a
> result of the default implementation of the ImageObserver interface in
> "this" - the parameter you give to us as your ImageObserver.
>
> I would edit your images again and turn off all options related to anything
> to do with animation or multi-frame images - inter-frame delays, loop
> counts, etc. As an alternative you can convert them to PNG images which
> should work on 1.4 and later runtimes (actually as far back as 1.2 I
> believe)...
>
> ...jim
>
> --On Monday, August 29, 2005 2:05 PM +0200 Olof Bjarnason
>
wrote:
>
> > Hi again java2d-list and Jim especially,
> >
> > OK I've tried to boil down the project as Jim suggested. At this
> > stage, if I remove anything I can't seem to reproduce the problem. If
> > you have interest enough to check it out, I am very thankful.
> >
> > First off, the Applet which shows the counts of updates, repaints and
> > paints. Note after some seconds the update count and the paint count
> > "runs away" - the "mad-update" behaviour:
> >
> > http://olofbjarnason.se/Terraformer/bin/Terraformer.html
> >
> > I've generated a javadoc tree, source code included:
> >
> > http://olofbjarnason.se/Terraformer/doc/index.html
> >
> > .. and also here is the source with resources:
> >
> > http://olofbjarnason.se/Terraformer/Terraformer.zip
> > (compile: javac *.java in terraformer directory, run with
> > Terraformer.html)
> >
> > Short project briefing:
> >
> > The Debug and GraphicsState classes are very small and have no
> > graphics/AWT code at all. The Model class is "purely logical" - the
> > simulation - it is quite big just skip checking it - it has no AWT
> > code either. The important classes I should guess are
> > TerraformerApplet and ResourceManager which do the AWT/graphics stuff,
> > alone. ResourceManager uses a MediaTracker to load the images
> > synchronously.
> >
> > Cya and thanks for you help,
> >
> > /Olof
> >
> >
> > On 8/26/05, Jim Graham wrote:
> >> We've probably exceeded the interest level of those here. The best
> >> thing at this stage would be to try to boil the test case down to the
> >> smallest case that still reproduces it (i.e. make a copy and start
> >> deleting/stubbing code while the problem still persists, etc.) and
> >> then send it to just me and I'll take a look at it off-line...
> >>
> >> ...jim
> >>
> >>
> >> --On Thursday, August 25, 2005 11:39 PM +0200 Olof Bjarnason
> >>
wrote:
> >>
> >> > Is there any particular part of my source code you want me to post?
> >> > Posting the whole project seems a bit too much for a mailing list...
> >> >
> >> > Thanks for your help,
> >> >
> >> > /Olof
> >> >
> >> > On 8/25/05, Jim Graham wrote:
> >> >> Hi Olof,
> >> >>
> >> >> There is no hard requirement to use Swing. It does provide a number
> >> >> of features, such as automatic double buffering and Timers, which
> >> >> could save you some coding and debugging time, but it is also
> >> >> possible to roll your own as you have already done. Swing also
> >> >> provides a lot of features that you probably don't need in a web page
> >> >> game, though they shouldn't get in your way or hurt you.
> >> >>
> >> >> AWT is a lower level API, but still reasonably high level in the grand
> >> >> scheme of things (i.e. all of the GUI toolkits out there), so it is
> >> >> equally useful for your purposes...
> >> >>
> >> >> ...jim
> >> >>
> >> >> --On Thursday, August 25, 2005 8:37 PM +0200 Olof Bjarnason
> >> >>
wrote:
> >> >> > OK since I've got you attention, please give me an educated answer
> >> >> > to this:
> >> >> >
> >> >> > Should I use Swing exclusively for a web page game? Which version of
> >> >> > the JRE Firefox-plugin is stable for end-users if I decide to use
> >> >> > Swing instead of just ground-plate AWT?
> >> >> >
> >> >> > Thanks for your ideas,
> >> >> >
> >> >> > /Olof
> >> >>
> >> >>
> >> >
> >> > ======================================================================
> >> > === == To unsubscribe, send email to listserv@java.sun.com and include
> >> > in the body of the message "signoff JAVA2D-INTEREST". For general
> >> > help, send email to listserv@java.sun.com and include in the body of
> >> > the message "help".
> >>
> >>
> >>
>
>
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

Hi all!

Just finished a beta version of Terraformer, the results of my Applet
2d graphics development efforts. Tag line: a minimalistic SimCity
clone set in a SciFi environment

http://olofbjarnason.se/Terraformer/Index.html

Enjoy! FYI: finally, I choose a double-buffer with "smart updating"
(caching of information) to achieve as flicker-free-animation as I
could.

/Olof

On 8/30/05, Olof Bjarnason
wrote:
> I converted the .gif:s to .png:s (the Exorcist utility! nice try it)
> and judging by a first "feel run" of the program, the problem
> dissappered! :)
>
> Jim: I am very grateful to you. The paint program I use mention only
> one frame, but probably inserts some "waste info" in the gif:s anyway.
> I think I will mail them to ask them to let the user have more power
> over exactly what info goes into the gifs, or else just start using
> png instead.
>
> wall_8.gif was strange - dunno why it differed from the others. Used
> same program to save it. Actually, I had observed some "anomalities"
> during program execution with wall 8 - sometimes it just didn't show
> at all - guess I got the explanation now.
>
> Once again, thank you very much, now I can finish the game and I've
> also learned alot..
> I'm planning on making the game a "home page game" so maybe I'll keep
> you posted on the progress here..
>
> cya,
>
> /Olof
>
> On 8/29/05, Jim Graham wrote:
> > Several of your images have tags which identify them as animated images
> > even though they only have one frame defined. All of them have a "graphics
> > extension block" listing a non-zero "animation frame delay" which implies
> > that they are multi-frame GIF images with a delay between frames (40ms in
> > most cases).
> >
> > wall_8.gif also has a NETSCAPE2.0 "loop count" tag defined which is another
> > indicator that the image is animated.
> >
> > The repaints are our mechanism for getting you to render everything again
> > "when the next animated frame in the image you drew" is ready - it is a
> > result of the default implementation of the ImageObserver interface in
> > "this" - the parameter you give to us as your ImageObserver.
> >
> > I would edit your images again and turn off all options related to anything
> > to do with animation or multi-frame images - inter-frame delays, loop
> > counts, etc. As an alternative you can convert them to PNG images which
> > should work on 1.4 and later runtimes (actually as far back as 1.2 I
> > believe)...
> >
> > ...jim
> >
> > --On Monday, August 29, 2005 2:05 PM +0200 Olof Bjarnason
> >
wrote:
> >
> > > Hi again java2d-list and Jim especially,
> > >
> > > OK I've tried to boil down the project as Jim suggested. At this
> > > stage, if I remove anything I can't seem to reproduce the problem. If
> > > you have interest enough to check it out, I am very thankful.
> > >
> > > First off, the Applet which shows the counts of updates, repaints and
> > > paints. Note after some seconds the update count and the paint count
> > > "runs away" - the "mad-update" behaviour:
> > >
> > > http://olofbjarnason.se/Terraformer/bin/Terraformer.html
> > >
> > > I've generated a javadoc tree, source code included:
> > >
> > > http://olofbjarnason.se/Terraformer/doc/index.html
> > >
> > > .. and also here is the source with resources:
> > >
> > > http://olofbjarnason.se/Terraformer/Terraformer.zip
> > > (compile: javac *.java in terraformer directory, run with
> > > Terraformer.html)
> > >
> > > Short project briefing:
> > >
> > > The Debug and GraphicsState classes are very small and have no
> > > graphics/AWT code at all. The Model class is "purely logical" - the
> > > simulation - it is quite big just skip checking it - it has no AWT
> > > code either. The important classes I should guess are
> > > TerraformerApplet and ResourceManager which do the AWT/graphics stuff,
> > > alone. ResourceManager uses a MediaTracker to load the images
> > > synchronously.
> > >
> > > Cya and thanks for you help,
> > >
> > > /Olof
> > >
> > >
> > > On 8/26/05, Jim Graham wrote:
> > >> We've probably exceeded the interest level of those here. The best
> > >> thing at this stage would be to try to boil the test case down to the
> > >> smallest case that still reproduces it (i.e. make a copy and start
> > >> deleting/stubbing code while the problem still persists, etc.) and
> > >> then send it to just me and I'll take a look at it off-line...
> > >>
> > >> ...jim
> > >>
> > >>
> > >> --On Thursday, August 25, 2005 11:39 PM +0200 Olof Bjarnason
> > >>
wrote:
> > >>
> > >> > Is there any particular part of my source code you want me to post?
> > >> > Posting the whole project seems a bit too much for a mailing list...
> > >> >
> > >> > Thanks for your help,
> > >> >
> > >> > /Olof
> > >> >
> > >> > On 8/25/05, Jim Graham wrote:
> > >> >> Hi Olof,
> > >> >>
> > >> >> There is no hard requirement to use Swing. It does provide a number
> > >> >> of features, such as automatic double buffering and Timers, which
> > >> >> could save you some coding and debugging time, but it is also
> > >> >> possible to roll your own as you have already done. Swing also
> > >> >> provides a lot of features that you probably don't need in a web page
> > >> >> game, though they shouldn't get in your way or hurt you.
> > >> >>
> > >> >> AWT is a lower level API, but still reasonably high level in the grand
> > >> >> scheme of things (i.e. all of the GUI toolkits out there), so it is
> > >> >> equally useful for your purposes...
> > >> >>
> > >> >> ...jim
> > >> >>
> > >> >> --On Thursday, August 25, 2005 8:37 PM +0200 Olof Bjarnason
> > >> >>
wrote:
> > >> >> > OK since I've got you attention, please give me an educated answer
> > >> >> > to this:
> > >> >> >
> > >> >> > Should I use Swing exclusively for a web page game? Which version of
> > >> >> > the JRE Firefox-plugin is stable for end-users if I decide to use
> > >> >> > Swing instead of just ground-plate AWT?
> > >> >> >
> > >> >> > Thanks for your ideas,
> > >> >> >
> > >> >> > /Olof
> > >> >>
> > >> >>
> > >> >
> > >> > ======================================================================
> > >> > === == To unsubscribe, send email to listserv@java.sun.com and include
> > >> > in the body of the message "signoff JAVA2D-INTEREST". For general
> > >> > help, send email to listserv@java.sun.com and include in the body of
> > >> > the message "help".
> > >>
> > >>
> > >>
> >
> >
> >
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Ted Hill

There is a new book from Oreilly called

Killer Game Programming in Java

http://www.oreilly.com/catalog/killergame/

You might find Chapter 2 very interesting. He shows how to control both
UPS (updates per sec) and FPS (frames per sec) independently.

Here is the table of contents for chap 2.

Chap 2. An Animation Framework
Animation as a Threaded Canvas
Adding User Interaction
Converting to Active Rendering
FPS and Sleeping for Varying Times
Sleeping Better
FPS and UPS
Pausing and Resuming
Other Animation Approaches

-----Original Message-----
From: Discussion list for Java 2D API
[mailto:JAVA2D-INTEREST@JAVA.SUN.COM] On Behalf Of Olof Bjarnason
Sent: Thursday, August 25, 2005 12:05 PM
To: JAVA2D-INTEREST@JAVA.SUN.COM
Subject: Re: [JAVA2D] Problem with non-stopping calls to update()

Whoa. Things like this scares me:

http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
(look at the section under "The event dispatching thread", the red
section)

I get the general feeling the AWT/Swing developers have been trying to
let the application developers not worry about threads (eg. hiding the
AWT-Event thread etc.) but then, when you get to the bottom of things
you REALLY have to worry about threads.

Quote: "To avoid the possibility of deadlock, you must take extreme care
that Swing components and models are created, modified, and queried only
from the event-dispatching thread." I guess this applies to generel,
old-skool AWT too...

Wow. Great. I think I'm gonne build my own GUI toolkit inside my Applet
instead of using AWT ... Question is how do I avoid AWT altogether...

/Olof

On 8/25/05, Olof Bjarnason
wrote:
> Thanks for you answer Chet.
>
> On 8/25/05, Chet Haase wrote:
> > 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.
>
> OK, guess I misread the docs. Actually, I followed this tutorial to
> begin with: http://www.dgp.toronto.edu/~mjmcguff/learn/java/
>
> >
> > Update calls paint() internally, which means that it calls your
> > paint, which calls update, which ...
>
> Yes, if I don't override update().
>
> > 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.
> I'm using AWT I guess, no Swing. I'm trying to go for old-API in order

> to make the game runnable on more computers. I compile for 1.4.2, but
> I guess 1.4.2 has Swing so I could go for paintComponent, but my
> feeling is I should use paint(), eg.the tutorial uses paint().
> Comments?
>
> >
> > 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.
> Thanks for these tips, I will try and implement the
> update-only-changed-area thingy.
>
> Some things I've tried now:
>
> - I don't override update() (removed it completely from my Applet),
> and I put the painting code in paint(). No change.
> - I removed ALL repaint() calls from my Applet. Of course the graphics

> isn't updating at all to begin with, but then the mad-updating begins
> ... No change.
> - I changed to JRE 1.5.02. No change.
>
> Confused...
>
> /Olof
>
> >
> > 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 listserv@java.sun.com and include in
the body
> > > of the message "signoff JAVA2D-INTEREST". For general help, send
email to
> > > listserv@java.sun.com and include in the body of the message
"help".
> >
>

========================================================================
===
To unsubscribe, send email to listserv@java.sun.com and include in the
body of the message "signoff JAVA2D-INTEREST". For general help, send
email to listserv@java.sun.com and include in the body of the message
"help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

Thanks Ted that seems nice!

My progress so far: since Swing's Timer class is Swing (duh) I have to
convert my Applet to a JApplet, which means paintComponent instead of
paint for instance. Hope it is as simple as that...

/Olof

On 8/25/05, Ted Hill
wrote:
> There is a new book from Oreilly called
>
> Killer Game Programming in Java
>
> http://www.oreilly.com/catalog/killergame/
>
> You might find Chapter 2 very interesting. He shows how to control both
> UPS (updates per sec) and FPS (frames per sec) independently.
>
> Here is the table of contents for chap 2.
>
>
> Chap 2. An Animation Framework
> Animation as a Threaded Canvas
> Adding User Interaction
> Converting to Active Rendering
> FPS and Sleeping for Varying Times
> Sleeping Better
> FPS and UPS
> Pausing and Resuming
> Other Animation Approaches
>
>
>
> -----Original Message-----
> From: Discussion list for Java 2D API
> [mailto:JAVA2D-INTEREST@JAVA.SUN.COM] On Behalf Of Olof Bjarnason
> Sent: Thursday, August 25, 2005 12:05 PM
> To: JAVA2D-INTEREST@JAVA.SUN.COM
> Subject: Re: [JAVA2D] Problem with non-stopping calls to update()
>
>
> Whoa. Things like this scares me:
>
> http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
> (look at the section under "The event dispatching thread", the red
> section)
>
> I get the general feeling the AWT/Swing developers have been trying to
> let the application developers not worry about threads (eg. hiding the
> AWT-Event thread etc.) but then, when you get to the bottom of things
> you REALLY have to worry about threads.
>
> Quote: "To avoid the possibility of deadlock, you must take extreme care
> that Swing components and models are created, modified, and queried only
> from the event-dispatching thread." I guess this applies to generel,
> old-skool AWT too...
>
> Wow. Great. I think I'm gonne build my own GUI toolkit inside my Applet
> instead of using AWT ... Question is how do I avoid AWT altogether...
>
> /Olof
>
>
> On 8/25/05, Olof Bjarnason
wrote:
> > Thanks for you answer Chet.
> >
> > On 8/25/05, Chet Haase wrote:
> > > 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.
> >
> > OK, guess I misread the docs. Actually, I followed this tutorial to
> > begin with: http://www.dgp.toronto.edu/~mjmcguff/learn/java/
> >
> > >
> > > Update calls paint() internally, which means that it calls your
> > > paint, which calls update, which ...
> >
> > Yes, if I don't override update().
> >
> > > 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.
> > I'm using AWT I guess, no Swing. I'm trying to go for old-API in order
>
> > to make the game runnable on more computers. I compile for 1.4.2, but
> > I guess 1.4.2 has Swing so I could go for paintComponent, but my
> > feeling is I should use paint(), eg.the tutorial uses paint().
> > Comments?
> >
> > >
> > > 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.
> > Thanks for these tips, I will try and implement the
> > update-only-changed-area thingy.
> >
> > Some things I've tried now:
> >
> > - I don't override update() (removed it completely from my Applet),
> > and I put the painting code in paint(). No change.
> > - I removed ALL repaint() calls from my Applet. Of course the graphics
>
> > isn't updating at all to begin with, but then the mad-updating begins
> > ... No change.
> > - I changed to JRE 1.5.02. No change.
> >
> > Confused...
> >
> > /Olof
> >
> > >
> > > 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 listserv@java.sun.com and include in
> the body
> > > > of the message "signoff JAVA2D-INTEREST". For general help, send
> email to
> > > > listserv@java.sun.com and include in the body of the message
> "help".
> > >
> >
>
> ========================================================================
> ===
> To unsubscribe, send email to listserv@java.sun.com and include in the
> body of the message "signoff JAVA2D-INTEREST". For general help, send
> email to listserv@java.sun.com and include in the body of the message
> "help".
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Chet Haase

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 listserv@java.sun.com and include in the body
> of the message "signoff JAVA2D-INTEREST". For general help, send email to
> listserv@java.sun.com and include in the body of the message "help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

Thanks for you answer Chet.

On 8/25/05, Chet Haase wrote:
> 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.

OK, guess I misread the docs. Actually, I followed this tutorial to begin with:
http://www.dgp.toronto.edu/~mjmcguff/learn/java/

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

Yes, if I don't override update().

> 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.
I'm using AWT I guess, no Swing. I'm trying to go for old-API in order
to make the game runnable on more computers. I compile for 1.4.2, but
I guess 1.4.2 has Swing so I could go for paintComponent, but my
feeling is I should use paint(), eg.the tutorial uses paint().
Comments?

>
> 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.
Thanks for these tips, I will try and implement the
update-only-changed-area thingy.

Some things I've tried now:

- I don't override update() (removed it completely from my Applet),
and I put the painting code in paint(). No change.
- I removed ALL repaint() calls from my Applet. Of course the graphics
isn't updating at all to begin with, but then the mad-updating begins
... No change.
- I changed to JRE 1.5.02. No change.

Confused...

/Olof

>
> 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 listserv@java.sun.com and include in the body
> > of the message "signoff JAVA2D-INTEREST". For general help, send email to
> > listserv@java.sun.com and include in the body of the message "help".
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Olof Bjarnason

Whoa. Things like this scares me:

http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
(look at the section under "The event dispatching thread", the red section)

I get the general feeling the AWT/Swing developers have been trying to
let the application developers not worry about threads (eg. hiding the
AWT-Event thread etc.) but then, when you get to the bottom of things
you REALLY have to worry about threads.

Quote: "To avoid the possibility of deadlock, you must take extreme
care that Swing components and models are created, modified, and
queried only from the event-dispatching thread." I guess this applies
to generel, old-skool AWT too...

Wow. Great. I think I'm gonne build my own GUI toolkit inside my
Applet instead of using AWT ... Question is how do I avoid AWT
altogether...

/Olof

On 8/25/05, Olof Bjarnason
wrote:
> Thanks for you answer Chet.
>
> On 8/25/05, Chet Haase wrote:
> > 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.
>
> OK, guess I misread the docs. Actually, I followed this tutorial to begin with:
> http://www.dgp.toronto.edu/~mjmcguff/learn/java/
>
> >
> > Update calls paint() internally, which means that it calls
> > your paint, which calls update, which ...
>
> Yes, if I don't override update().
>
> > 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.
> I'm using AWT I guess, no Swing. I'm trying to go for old-API in order
> to make the game runnable on more computers. I compile for 1.4.2, but
> I guess 1.4.2 has Swing so I could go for paintComponent, but my
> feeling is I should use paint(), eg.the tutorial uses paint().
> Comments?
>
> >
> > 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.
> Thanks for these tips, I will try and implement the
> update-only-changed-area thingy.
>
> Some things I've tried now:
>
> - I don't override update() (removed it completely from my Applet),
> and I put the painting code in paint(). No change.
> - I removed ALL repaint() calls from my Applet. Of course the graphics
> isn't updating at all to begin with, but then the mad-updating begins
> ... No change.
> - I changed to JRE 1.5.02. No change.
>
> Confused...
>
> /Olof
>
> >
> > 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 listserv@java.sun.com and include in the body
> > > of the message "signoff JAVA2D-INTEREST". For general help, send email to
> > > listserv@java.sun.com and include in the body of the message "help".
> >
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".