Thanks for you answer Chet. On 8/25/05, Chet Haase <[EMAIL PROTECTED]> 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 [EMAIL PROTECTED] and include in the body > > of the message "signoff JAVA2D-INTEREST". For general help, send email to > > [EMAIL PROTECTED] and include in the body of the message "help". > =========================================================================== To unsubscribe, send email to [EMAIL PROTECTED] and include in the body of the message "signoff JAVA2D-INTEREST". For general help, send email to [EMAIL PROTECTED] and include in the body of the message "help".