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 }