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 }