001 /** 002 * @author Václav Mikolášek 003 * nicklaus@students.zcu.cz 004 */ 005 006 package animace; 007 008 import javax.swing.*; 009 import java.awt.*; 010 import java.awt.image.*; 011 import java.util.*; 012 013 /** 014 * Třída Driver poskytuje vlákno, které má za úkol pohybovat 015 * s jedním objektem typu Moveable. Pričemž umožňuje použití 016 * PaintControleru, který zaručuje, že s objektem není proveden 017 * dalši pohyb, dokud není stará pozice objektu vykreslena 018 */ 019 public class Driver extends Thread { 020 private Moveable object; // s timto objektem se bude pohybovat 021 private float step = 1f; // znamena o kolik pixelu se posouva za jedno kolo 022 private float stepCount = 0f; // znamena o kolik pixelu se jiz pohnul; 023 private float dirX = -1f; // dirX a dirY urcuji, kterym smerem se objekt pohybuje 024 private float dirY = 1f; 025 private int locationX = 0; // souradnice pozice obdelniku, ve kterem se muze objekt pohybovat 026 private int locationY = 0; 027 private int width = 0; // rozmer oblasti, ve ktere se objekt pohybuje 028 private int height = 0; 029 private boolean goes = false; // zda jede nebo stoji 030 private long time = -1; 031 private PaintControl pc = null; // PaintControl pc 032 033 /** 034 * Vytvoří řidiče pro objekt implemenujicí rozhraní Moveable. Objekt se bude pohybovat 035 * v obdelníku určeném parametry locationX, locationY (umístěni), width a height 036 * @param object Moveable objekt, s kterým bude Driver lomcovat. 037 * @param locationX ukotvení na ose x oblasti (obdélníku), ve kterém se objekt pohybuje. 038 * @param locationY ukotvení téže oblasti na ose y. 039 * @param width šířka oblasti. 040 * @param height výška oblasti. 041 */ 042 public Driver(Moveable object,int locationX,int locationY,int width,int height) { 043 this.object = object; 044 this.locationX = locationX; 045 this.locationY = locationY; 046 this.width = width; 047 this.height = height; 048 } 049 050 /** 051 * Touto metodou lze uvést "Drivera" do pohybu 052 */ 053 public void start() { 054 this.goes = true; 055 super.start(); 056 } 057 058 /** 059 * Podavá informaci o stavu řidiče. 060 */ 061 public boolean goes() { 062 return goes; 063 } 064 /** 065 * Zastaví řidiče 066 */ 067 public void stopDriving() { 068 goes = false; 069 } 070 /** 071 * Vrací údaj o tom, jak dlouho vlákno běželo. 072 */ 073 public long getTime() { 074 return time; 075 } 076 077 /** 078 * Nastaví směr jakým se bude objekt pohybovat, mají smysl pouze celá čísla, protože 079 * location se uchovává v celých číslech. 080 */ 081 public void setDir(float dirX, float dirY) { 082 this.dirX = dirX; 083 this.dirY = dirY; 084 } 085 086 /** 087 * Program běhu vlákna. Vlákno se rozeběhne a beží dokud jej nějaké jiné vlákno 088 * nezastaví voláním <tt>stopDriving()</tt> nebo až se objekt 5000x posune. 089 */ 090 public synchronized void run() { 091 stepCount = 0; 092 step = 1f; 093 long timeAtStart = System.currentTimeMillis(); 094 095 /// zacni pocitat fps 096 if (pc != null) { 097 pc.fps(true); 098 } 099 while (goes && stepCount < 5000) { 100 move(); 101 stepCount++; 102 if (pc != null) { 103 pc.objectMoved(); 104 } 105 else { 106 try { sleep(10);} 107 catch (InterruptedException e) {;} 108 } 109 } 110 goes = false; 111 /// kdyz dobehl, uz nepocitej FPS 112 if (pc != null) { 113 pc.fps(false); 114 } 115 long timeAtStop = System.currentTimeMillis(); 116 this.time = timeAtStop - timeAtStart; 117 } 118 119 /** 120 * Tato metoda implementuje jednoduchý algoritmus pohybu 121 * pohne s objektem, vždy pouze o jeden "step", implicitně nastaven na 1 pixel 122 */ 123 private void move() { 124 Point location = object.getLocation(); 125 if (location.x < locationX - (step * dirX)) { 126 dirX = Math.abs(dirX); 127 } 128 if (location.x > width - (step * dirX)) { 129 dirX = -Math.abs(dirX); 130 } 131 if (location.y < locationY - (step * dirY)) { 132 dirY = Math.abs(dirY); 133 } 134 if (location.y > height - (step * dirY)) { 135 dirY = -Math.abs(dirY); 136 } 137 138 object.setLocation(Math.round(location.x + (dirX * step)), Math.round(location.y + (dirY * step))); 139 } 140 141 /** 142 * Umožní nastavit kontrolu, která se startá o průběh vykreslování objektu 143 */ 144 public void setPaintControl(PaintControl pc) { 145 this.pc = pc; 146 } 147 }