[java] Qs about refreshing, time and optimization

Started by
6 comments, last by Cedric 21 years, 6 months ago
1. I heard that there is no high-precision timer in Java. Is the Date the best we can get? On my computer, I get a "tick" every 15-16 seconds, which is not very good. I suppose that I could improve this precision by evaluating the average time of a frame over a long period, but still, that would be tricky... 2. My code for paint():
  
		bimg = (BufferedImage) createImage(g.getClipBounds().width, g.getClipBounds().height);
		Graphics2D g2 = bimg.createGraphics();

		g2.translate(0, g.getClipBounds().height);
		g2.scale(1, -1);

		g2.draw(new Line2D.Float(30,30,40,40));

		graphics.drawImage(bimg, 0, 0, this);


  
Is there anything wrong with this? It flickers a little bit on AppletViewer. (Note: I just realized that a new BufferedImage is created at every frame, which is probably not efficient, so forget about that mistake. It should not fix my flicker problem, though) I''ve got another thread going on a perpetual while loop, asking for a repaint and updating objects positions. Should it Thread.sleep(x)? It doesn''t seem to affect the outcome very much. Finally, any optimization tips? I''m coming from a C++ background, and I''ve come to know the various optimization tricks, but in Java, a lot of them are lost (micro-optimization, anyway). Using templates vs using virtual functions is not even an issue. Is there any function inlining in Java? Thank you, Cédric
Advertisement
... and while we''re at it, there is a Thread.sleep function that accepts nanoseconds as its argument. Is it really that precise? If so, why isn''t it used for the Date class?

Cédric
... and while we're at it, there is a Thread.sleep function that accepts nanoseconds as its argument. Is it really that precise? If so, why isn't it used for the Date class?

It is as precise as the environment your program is running in. The Date class is another thing, I don't think they had in mind extremely small time intervals when they designed that class...

Mac for productivity
Linux for development
Palm for mobility
Windows... for the Solitaire

[edited by - cyrax256 on October 3, 2002 11:02:41 PM]
Ciro Durán :: My site :: gamedev.net :: AGS Forums
1. The best timer you can get under windows is System.currentTimeMillis() which gets about 50 millisec accuracy. To do better you have to implement a thread and count ticks and average them.

2. You sound like you want to get the fastest drawing you can; Getting the fastest 2d graphics under java is a very tricky and you don''t do it by translating and scaling an image with Graphics2D. For a really complete discussion head over to the javagaming.org forums were its all laid out in detail also you can find a couple of articles by the Sun programmers that design the stuff. Check into jdk 1.4 and volatile images.

3. Thread.sleep() is that precise under linux.
go to Javagaming.org and do a search on high precision timer. That problem has been solved even in 1.3 or lower. Also, you will have to implement double buffering yourself if you really want to top the flickering. It''s not difficult at all. The answer to that can be found on javagaming.org too.
you can use this as a timer, it works a lot better than any other solution i''ve seen (well, using a native timer through JNI is better in some ways, and worse in some ways). this is the one from javagaming.org and i can''t remember who wrote it so i can''t credit him


  public class HighresTimer implements Runnable {	private int ticks, autoLength;	private Thread timerThread;	private boolean autoCorrection = true;	private boolean running = false;	private long timeDiff, startTime, endTime, msDelay, targetMs;	public HighresTimer() {		timerThread = new Thread(this);		timerThread.setPriority(Thread.MAX_PRIORITY);		timerThread.setDaemon(true);	}	public int getTickCount() {		return ticks;	}	public void resetTickCount() {		ticks = 0;	}	public void startTimer() {		running = true;		timerThread.start();	}	public void stopTimer() {		running = false;		try {			timerThread.join();		}		catch (Exception e) {		}	}	public void setAutoCorrection(boolean on, int sampleLength) {		autoCorrection = on;		autoLength = sampleLength;	}	public void setDelay(int tmsDelay) {		msDelay = tmsDelay;		targetMs = msDelay;	}	public void run() {		startTime = System.currentTimeMillis();		try {			while (running) {				if (msDelay > 0)					Thread.sleep(msDelay);				ticks++;				synchronized (this) {					notifyAll();				}				if (autoCorrection && (ticks % autoLength == 0)) {					endTime = System.currentTimeMillis();					timeDiff = ((endTime - startTime) / autoLength) - targetMs;					startTime = endTime;					if (timeDiff > 0) {						msDelay--;					}					if (timeDiff < 0) {						msDelay++;					}				}			}		}		catch (Exception e) {		}	}}  


to get rid of the flickering, you need to use double buffering, that is, you draw everything onto an offscreen image, and when everything is drawn onto that, you flip.

i found this over at java.sun.com:

http://java.sun.com/docs/books/tutorial/extra/fullscreen/doublebuf.html
http://java.sun.com/docs/books/tutorial/2d/images/doublebuffering.html

that''s the "old" way to do it, and it works just fine. you can however have it done automagically by using BufferStrategies.

see http://java.sun.com/docs/books/tutorial/extra/fullscreen/bufferstrategy.html for more info.

hope this helps!

_______________________
http://mill.3dfxsweden.net
_______________________ http://mill.3dfxsweden.net
Thank you! I had completely forgotten about javagaming.org. I''m heading to that site now.

But, one thing though... bslayerw and mill-o, you both told me that I need double buffering. I''m confused, because I thought that the code I shown in my OP was indeed double buffering. Am I missing something?

Cédric
Well, you do double-buffer the drawing you do. But you haven''t double-buffered all the drawing Applet does. You need to override the update method in Applet, so that it double-buffers. Otherwise, you''ll always have flickering. (At least using AWT components...)


  public void update(Graphics g){    Image i = createImage(getWidth(), getHeight());    Graphics buffered = i.getGraphics();    buffered.setClip(g.getClip());    super.update(buffered);    g.drawImage(i, 0, 0, this);    buffered.dispose();}  


That should do what you want. However, I haven''t checked it, so make sure of that...

This topic is closed to new replies.

Advertisement