001 /**
002 * @author Václav Mikolášek
003 * nicklaus@students.zcu.cz
004 */
005
006 package animace;
007
008 import java.util.*;
009
010 /**
011 * Tato třída slouží ke kontrole kreslení různých objektů, může měrit jak
012 * často jsou tyto objekty překreslovány (fps).
013 * Metody <tt>objectMoved</tt> a <tt>objectPainted</tt> jsou synchronizované, protože se
014 * předpokláda, že pohyb objektu a jeho vykreslování jsou řízeny různými vlákny.
015 * Potom PaintControl zařídí, že se s objektem nepohne dříve, dokud není jeho
016 * pozice také nakreslena.
017 */
018
019 public class PaintControl {
020
021 /**
022 * painted, kontrolní podmínková proměnná. Z vnějšku by se neměla měnit
023 * jinak, než přes metody <tt>objectMoved</tt> a <tt>objectPainted</tt>,
024 * Není důvod porč by nemohla být <b><tt>private</tt></b>. :-)
025 */
026 public boolean painted = false;
027 /**
028 * Počet snímků = počet zavolání metody <tt>objectPainted</tt>.
029 */
030 public int framesCount = 0;
031 /**
032 * počet pohybů = počet zavolání metody <tt>objectMoved</tt>,
033 */
034 public int movesCount = 0;
035
036 private boolean fpsOn = false;
037 private double fps = 0;
038 private double averageFps = 0;
039 private long timeLast = 0;
040 private long timeFirst = 0;
041 private long timeFirstMillis = 0;
042 private long timeStopedMillis = 0;
043 private double maxFps = 0;
044 private double minFps = Double.MAX_VALUE;
045
046 /**
047 * Když se s objektem pohne a je zavolána tato metoda, pozastaví se vlákno a čeká,
048 * než vlákno které se stará o vykreslování zavolá metodu objectPainted().
049 */
050 public synchronized void objectMoved() {
051 movesCount++;
052 while (!painted)
053 try {
054 wait();
055 }
056 catch (InterruptedException e) {;}
057 painted = false;
058 }
059
060 /**
061 * Tato metoda vzbudí případné vlákno, které čekalo, než
062 * je objekt znovu překereslen.
063 */
064 public synchronized void objectPainted() {
065 if (fpsOn) {
066 countFps();
067 }
068 if (!painted){
069 painted = true;
070 notifyAll();
071 }
072 }
073
074 /**
075 * Počítá FPS, jak aktuální, tak i průměrné. Pro akutální FPS je nutné použít metodu
076 * System.nanoTime(), která je v SDK od verze SDK 1.5 odkomentujte text, v případe, že
077 * pouzivate tuto verzi nebo vyšší.
078 */
079 public double countFps() {
080 if (timeFirstMillis == 0)
081 timeFirstMillis = System.currentTimeMillis();
082 /* od verze SDK 1.5
083 if (timeLast == 0)
084 timeLast = System.nanoTime();
085 if (timeFirst == 0)
086 timeFirst = System.nanoTime();
087 */
088 else {
089 averageFps = (1000d*framesCount/(System.currentTimeMillis() - timeFirstMillis));
090 /* od verze SDK 1.5
091 long timeNow = System.nanoTime();
092 fps = 1000000000d / (timeNow - timeLast);
093 maxFps = fps > maxFps ? fps : maxFps;
094 minFps = fps < minFps ? fps : minFps;
095 timeLast = timeNow;
096 */
097 framesCount++;
098 }
099 return fps;
100 }
101
102 /**
103 * Nastaví, zda bude PaintControl počítat, jak často je objekt překreslován
104 */
105 public void fps(boolean val) {
106 fpsOn = val;
107 /// jestlize bylo pocitani rozbehnuto, resetuj stav
108 if (fpsOn) {
109 timeLast = 0;
110 timeFirst = 0;
111 timeFirstMillis = System.currentTimeMillis();
112 framesCount = 0;
113 movesCount = 0;
114 }
115 }
116 /**
117 * Vrací aktuální FPS
118 */
119 public double getFps() {
120 return fps;
121 }
122
123 /**
124 * Vrací průměrné FPS od doby kdy bylo zapnuto počítání metodou
125 * <tt>fps(true)</tt> do doby než je opět vypnuto.
126 */
127 public double getAverageFps() {
128 return averageFps;
129 }
130 /**
131 * Vrací maximální FPS
132 */
133 public double getMaxFps() {
134 return maxFps;
135 }
136 /**
137 * Vrací minimální FPS
138 */
139 public double getMinFps() {
140 return minFps;
141 }
142 }