package engineControl; import game.Move; import gui.Gui; /** * Die Klasse MovementControl ist für die Bewegung des Roboters zuständig * Dabei handelt es sich um ein Singleton-Entwurfsmuster, damit nur eine Instanz der Klasse erstellt werden kann * Beim erstellen der Instanz wird eine Bluetooth Verbindung zwischen Rechner und beiden NXT-Blöcken etabliert * Bei Übergabe eines Move-Objektes und einem Aufruf von moveRobot wird die Bewegung ausgeführt * * @author Rudolf Martin * */ public class MovementControl { /** * Verbindung zum NXT-25 */ private ConnServ con_Nxt25; /** * Verbindung zum NXT-23 */ private ConnServ con_Nxt23; /** * */ //private boolean gameExists = true; /** * Move-Objekt mit den Informationen über den aktuellen Zug */ private Move movefigure; /** * Instanz der Klasse */ private static MovementControl instance = null; /** * Singleton Konstruktor * Erstellt Verbindung zu NXT23 und 25 */ private MovementControl() { System.out.println("Verbindung zu den NXT's wird hergestellt..."); this.con_Nxt25 = new ConnServ("NXT_25"); this.con_Nxt23 = new ConnServ("NXT_23"); //Prüfe ob eine Verbindung vorhanden ist if(this.con_Nxt23.getConnectionInformation() == null || this.con_Nxt25.getConnectionInformation() == null) { Gui.getInstance().showWarning("Es konnte keine Verbindung zu beiden NXT's hergestellt werden!"); System.exit(0); } else { System.out.println("Verbindung erfolgreich!"); } } /** * Erstellt eine Instanz der Klasse, falls bereits eine existiert wird auf diese verwiesen * * @return MovementControl-Instanz */ public static MovementControl getInstance() { if (instance == null) { instance = new MovementControl(); } return instance; } /* *Main-Methode dient nur zu Tests */ public static void main(String[] args) { /* * Erstelle Instanz der Klasse zum testen */ Move testgame; for (int i = 0;i<11;i++) { MovementControl m = MovementControl.getInstance(); switch(i) { case 0: testgame = new Move((byte)1,9,25,false); m.setMovefigure(testgame); break; case 1: testgame = new Move((byte)1,13,29,false); m.setMovefigure(testgame); break; case 2: testgame = new Move((byte)1,7,24,false); m.setMovefigure(testgame); break; case 3: testgame = new Move((byte)1,5,32,false); m.setMovefigure(testgame); break; case 4: testgame = new Move((byte)1,9,25,false); testgame.setQueenSideCastling(true); m.setMovefigure(testgame); break; case 5: testgame = new Move((byte)1,2,19,false); m.setMovefigure(testgame); break; case 6: testgame = new Move((byte)1,3,10,true); m.setMovefigure(testgame); break; case 7: testgame = new Move((byte)1,1,25,true); m.setMovefigure(testgame); break; case 8: testgame = new Move((byte)1,25,57,false); m.setMovefigure(testgame); break; case 9: testgame = new Move((byte)1,57,1,false); m.setMovefigure(testgame); break; case 10: testgame = new Move((byte)1,32,60,false); m.setMovefigure(testgame); break; } m.moveRobot(); } } /** * Methode die den Befehl zur Bewegung nach unten versendet * */ private void moveDown() { //An den NXT wird der befehl zur Runterbewegung gesendet //Zehnerstelle ist unwichtig, die 3 sagt dem NXT welchen motor er ansprechen muss this.con_Nxt23.sendInt(13); if(this.con_Nxt23.getInt() == -1) { System.out.println("Fehler Bewege Runter"); System.out.println("Es wurde nicht der richtige Rückgabewert übermittelt"); } } /** * Methode die den Befehl zur Bewegung nach oben versendet * */ private void moveUp() { //An den NXT wird der befehl zur Runterbewegung gesendet //Zehnerstelle ist unwichtig, die 4 sagt dem NXT welchen motor er ansprechen muss this.con_Nxt23.sendInt(14); if(this.con_Nxt23.getInt() == -1) { System.out.println("Fehler Bewege Hoch"); System.out.println("Es wurde nicht der richtige Rückgabewert übermittelt"); } } private void grabFigure() { this.con_Nxt25.sendInt(13); if (this.con_Nxt25.getInt()==-1) { System.out.println("Fehler Greife Figur"); } } private void dropFigure() { this.con_Nxt25.sendInt(14); if(this.con_Nxt25.getInt()==-1) System.out.println("Fehler Figur loslassen"); } /** * Methode zur Bewegung zum übergebenen Feld * * @param row Zielreihe * @param column Zielspalte */ private void moveToField(int row, int column) { System.out.println("Sende Koordinaten..."); this.con_Nxt23.sendInt(row); this.con_Nxt25.sendInt(column); System.out.println("Warte auf Antwort..."); int doneRow = this.con_Nxt23.getInt(); int doneColumn = this.con_Nxt25.getInt(); if (doneRow != 1 && doneColumn != 1) { System.out.println("Es wurde nicht der richtige Wert zurückgegeben, Bewegung unerfolgreich"); } else { System.out.println("Bewegung erfolgreich"); } } /** * Methode zur Bewegung zum Startpunkt */ private void moveToInit() { //Zehnerstelle ist irrelevant, 5 sagt dem Roboter, dass er moveToInit verwenden soll this.con_Nxt23.sendInt(15); this.con_Nxt25.sendInt(15); int doneRow = this.con_Nxt23.getInt(); int doneColumn = this.con_Nxt25.getInt(); if (doneRow != 1 && doneColumn != 1) { System.out.println("Es wurde nicht der richtige Wert zurückgegeben, Bewegung unerfolgreich"); } else { System.out.println("Bewegung erfolgreich"); } } /** * Methode zur Roboterbewegung des aktuellen move objektes * Sendet Koordinaten an die beiden NXT-Bloecke * * @return True bei erfolgreicher Bewegung */ public boolean moveRobot() { /* * @see createIntForSending */ int concatenatedCoords = this.createIntForSending(); /* * Prüft ob es sich um eine kleine Rochade handelt und führt diese aus */ if(this.movefigure.isKingSideCastling() || this.movefigure.isQueenSideCastling()) { this.doCastling(); return true; } /* * Zu Erst werden die rowFrom und ColumnFrom Koordinaten an beide NXT Blöcke versand, * damit gleichzeitig links rechts und vorwärts Bewegung ausgeführt wird */ int rowFrom = (concatenatedCoords/1000)%10; int columnFrom = concatenatedCoords/10000; int rowTo = (concatenatedCoords/10)%10; int columnTo = (concatenatedCoords/100)%10; rowFrom = rowFrom*10+1; columnFrom = columnFrom*10+1; rowTo = rowTo*10+1; columnTo = columnTo*10+1; try { //System.out.println("Warte 1 Sekunden vor dem Senden..."); Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread_Sleep wurde unterbrochen"); } //Teste ob auf dem Zielfeld die Figur geschlagen wurde //Wenn ja bringe sie erst weg bevor der Zug ausgeführt wird if(this.movefigure.isCaptured()) { this.removeCapturedFigure(rowTo, columnTo); } //Fahre zur ersten Koordinate this.moveToField(rowFrom, columnFrom); //Bewege Runter this.moveDown(); //Greife Figur this.grabFigure(); //Bewege Hoch this.moveUp(); //Fahre zur 2.Koordinate this.moveToField(rowTo, columnTo); //Fahre Runter this.moveDown(); //Lasse Figur los this.dropFigure(); //Fahre hoch this.moveUp(); //Bewege zum start this.moveToInit(); System.out.println("Zug beendet"); return true; } /* * * Methode für die kleine Rochade * Werte sind hart gecoded * * */ public void doCastling() { int rowFrom; int columnFrom; int columnTo; int rowTo; if (this.movefigure.isKingSideCastling()) { //Koordinaten für die erste Bewegung der kleinen Rochade (König von Feld 4 auf Feld 2) rowFrom = 11; columnFrom = 41; rowTo = 11; columnTo = 21; } else { //Koordinaten für die erste Bewegung der großen Rochade (König von Feld 4 auf Feld 6) rowFrom = 11; columnFrom = 41; rowTo = 11; columnTo = 61; } try { System.out.println("Warte 2 Sekunden vor dem Senden..."); Thread.sleep(2000); } catch (InterruptedException e) { System.out.println("Thread_Sleep wurde unterbrochen"); } /* * In der Schleife wird zunächst der König bewegt, im zweiten Durchgang dann der Turm * */ for(int i = 0;i<2;i++) { if (i == 1 && this.movefigure.isKingSideCastling()) { //Koordinaten um Turm von Feld 1 auf Feld 3 zu setzen columnFrom = 11; columnTo = 31; } else if (i == 1 && this.movefigure.isQueenSideCastling()) { //Koordinaten um Turm von Feld 8 auf Feld 5 zu setzen columnFrom = 81; columnTo = 51; } //Fahre zur ersten Koordinate this.moveToField(rowFrom, columnFrom); //Bewege Runter this.moveDown(); //Greife Figur this.grabFigure(); //Bewege Hoch this.moveUp(); //Fahre zur 2.Koordinate this.moveToField(rowTo, columnTo); //Fahre Runter this.moveDown(); //Lasse Figur los this.dropFigure(); //Fahre hoch this.moveUp(); } //Fahre zurück zum start this.moveToInit(); System.out.println("Zug beendet"); } /* * Methode, welche die geschlagene Figur auf Init-Pos schmeisst * */ public void removeCapturedFigure(int rowTo, int columnTo) { //Fahre zur ersten Koordinate this.moveToField(rowTo, columnTo); //Bewege Runter this.moveDown(); //Greife Figur this.grabFigure(); //Bewege Hoch this.moveUp(); //Bewege zum start this.moveToInit(); //Lasse Figur los this.dropFigure(); } /* * Liest FieldFrom und FieldTo aus dem Move Objekt raus und schreibt es in einen * konkatenierten Integer Wert der Form: (RowFrom)+(ColumnFrom)+(RowTo)+(ColumnTo)+(Capture) * */ public int createIntForSending() { int[] x_y = new int[4]; int FieldFrom = 65-this.movefigure.getFieldFrom(); int FieldTo = 65-this.movefigure.getFieldTo(); if (FieldFrom % 8 == 0) { x_y[0] = 8; x_y[1] = (int) Math.ceil(FieldFrom / 8.0); } else { x_y[0] = FieldFrom % 8; x_y[1] = (int) Math.ceil(FieldFrom / 8.0); } if (FieldTo % 8 == 0) { x_y[2] = 8; x_y[3] = (int) Math.ceil(FieldTo / 8.0); } else { x_y[2] = FieldTo % 8; x_y[3] = (int) Math.ceil(FieldTo / 8.0); } int concatenatedCoords = (((0+x_y[0])*10 + x_y[1])*10 + x_y[2])*10 + x_y[3] ; int capture = this.movefigure.isCaptured()? 1:0; concatenatedCoords = concatenatedCoords*10 + capture; return concatenatedCoords; } /* * Set-Methode für das attribut gameExists */ // public void setGameExists(boolean gameExists) { // this.gameExists = gameExists; // } /* * Set-Methode für das Move-Objekt * */ public void setMovefigure(Move movefigure) { this.movefigure = movefigure; } }