200 likes | 344 Views
Battleship Mobile. Marcus Degwert Marcus Pflanz Martin Fleckner Christian Reibeholz Matthias Lauffer Erfurt University of Applied Sciences. Sommersemester 2010. Agenda. Demo Konzept BlueTooth Verbindungsaufbau BT-Nutzung & Anbindung an das Gameplay Gameplay StateMachine Sound-Effekte
E N D
Battleship Mobile Marcus Degwert Marcus Pflanz Martin Fleckner Christian Reibeholz Matthias Lauffer Erfurt University of Applied Sciences Sommersemester 2010
Agenda Demo Konzept BlueTooth Verbindungsaufbau BT-Nutzung & Anbindung an das Gameplay Gameplay StateMachine Sound-Effekte Grafik
Schiffeversenken, engl.: Battleship / Battleships Konzept • gegeneinander via BlueTooth spielbar
Bluetooth – verwendete Libaries • import javax.bluetooth.*; • import javax.microedition.io.Connector; • import javax.microedition.io.StreamConnection; • import java.io.IOException; • import java.io.InputStream; • import java.io.OutputStream; • import java.util.Hashtable; • import java.util.Vector;
Bluetooth – Server • final class BTServer implements Runnable { • . • . • . • private static final UUID BATTLESHIPS_SERVER_UUID = • new UUID ("F0E0D0C0B0A000908070605040302010", false); • private LocalDevice localDevice; • private StreamConnectionNotifier notifier; • private ServiceRecord record; • private boolean isClosed; • private ClientProcessor processor; • private final Hashtable dataElements = new Hashtable (); • private StreamConnection connection; • private int state = 0; • . • . • . • }
Bluetooth – Server • public void run () { • … • localDevice = LocalDevice.getLocalDevice (); • if (!localDevice.setDiscoverable (DiscoveryAgent.GIAC)) { • … • } • StringBuffer url = new StringBuffer ("btspp://"); • url.append ("localhost").append (':'); • url.append (BATTLESHIPS_SERVER_UUID.toString ()); • url.append (";name=Picture Server"); • url.append (";authorize=false"); • notifier = (StreamConnectionNotifier) Connector.open (url.toString ()); • … • // ok, start processor now • processor = new ClientProcessor (); • … • this.connection = notifier.acceptAndOpen (); • … • input = this.connection.openInputStream(); • output = this.connection.openOutputStream(); • … • }
Bluetooth - Client • final class BTClient implements Runnable, DiscoveryListener { • … • private static final UUID BATTLESHIPS_SERVER_UUID = • new UUID ("F0E0D0C0B0A000908070605040302010", false); • private static final int DEVICE_SEARCH = 1; • private static final int SERVICE_SEARCH = 2; • private DiscoveryAgent discoveryAgent; • private Vector /* RemoteDevice */ devices = new Vector (); • private Vector /* ServiceRecord */ records = new Vector (); • private Hashtable base = new Hashtable (); • private LocalDevice localDevice; • … • }
Bluetooth - Client • public void run () { • … • this.localDevice = LocalDevice.getLocalDevice (); • discoveryAgent = this.localDevice.getDiscoveryAgent (); • … • this.EstablishConnection(); • … • } • private synchronized void EstablishConnection () { • … • if (!searchDevices ()) { • return; • } • … • if (!searchServices ()) { • return; • } • … • if (this.Connect()) { • … • this.input = this.connection.openInputStream(); • this.output = this.connection.openOutputStream(); • … • }
Bluetooth - Client • private boolean searchDevices () { • … • discoveryAgent.startInquiry (DiscoveryAgent.GIAC, this); • … • } • private boolean searchServices () { • … • for (int i = 0; i < devices.size (); i++) { • RemoteDevice rd = (RemoteDevice) devices.elementAt (i); • … • searchIDs[i] = discoveryAgent.searchServices (attrSet, uuidSet, rd, this); • … • } • … • }
Bluetooth - Client • public boolean Connect() { • … • String[] urls = new String[this.records.size()]; • for (int i = 0; i < this.records.size(); i++) { urls[i]=((ServiceRecord)(this.records.elementAt(i))). • getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); • } • … • this.connection = (StreamConnection)Connector.open(urls[i]); • … • }
BT-Nutzung & Anbindung an das Gameplay BlueTooth-Thread ruft öffentliche Methoden des Spielfeldes auf BlueTooth-Thread als Ausgangspunkt für das Gameplay Contra: keine saubere Trennung zwischen Netzwerk und Gameplay Pro: einfache (leicht verständliche) State-Machine sofortiges Senden/Empfangen von BT-Übertragungen keine Notwendigkeit für Mechanismen zur Thread-Synchronisierung
BT-Nutzung & Anbindung an das Gameplay Nachrichtenaufbau: MessageType + SessionID + MessageID + X-Coord + Y-Coord MessageType - gibt an um welche Nachricht es sich handelt SessionID - einzigartige ID der aktuellen Sitzung MessageID - Sitzungsweite einzigartige ID dieser Nachricht X-Coord/Y-Coord - Koordinaten bei Beschuss/Beschussantwort (optional)
MessageTypes: * BTK // other device is successfully set up and ready * RDY // opponent has placed its ships and is waiting for other player * STC // both players ready - client starts shooting * STS // both players ready - server starts shooting * QIT // player wants to leave the session or timeout * * SHT // shot at given coords * WTR // shot with according sequence number dropped into water * HIT // shot with according sequence number hit an enemy ship * SNK // shot with according sequence number hit and destroyed a ship BT-Nutzung & Anbindung an das Gameplay
BT-Nutzung & Anbindung an das Gameplay • public boolean Shoot(Position pos) • { • // build the message • String message = SHOOT + • CONCAT + • this.sessionId + • CONCAT + • this.messageId + • CONCAT + • String.valueOf(pos.X()) + • CONCAT + • String.valueOf(pos.Y()); • boolean result = this.SendMessage(message); • [...]
BT-Nutzung & Anbindung an das Gameplay • // -- read MessageType -- • concatIndex = message.indexOf(CONCAT); • if (concatIndex == -1) • { • System.err.println("failed reading first CONCAT"); • return; • } • messageType = message.substring(0, concatIndex); • System.out.print("reading message. type: " + messageType);
Soundeinbindung I Problem: sequenzieller Ablauf im Programm „Player“ blockiert weitere Interaktion bis „Player“ in den Zustand „PREFETCHED“ über geht (END_OF_MEDIA, STOPPED) Lösung: Sound Hilfsklasse „BMESound“ welche einen neuen Thread startet Implementiert das Interface „Runnable“ Jede Instanz von „BMESound“ erstellt neuen Thread Paralleler Ablauf
Soundeinbindung II importjavax.microedition.media.*; publicclassBMESoundimplementsRunnable{ private Player _player = null; private String _file = null; private String _type = null; privateboolean _bmesoundState = false; privateint _loopCount = 0; Thread _t = null; publicBMESound(String file, String type, intlCount){} publicvoidstart(){} publicvoidstop(){} publicvoidrun(){} }
Placing y n Shoot WeStart? WaitForShot Shot n n Hit? Water Hit? n y y ShowWater (1sec) n Finish? Finish? y y DisplayResult
Grafik • Darstellung des Spielfelds • Darstellung der Schiffe • Darstellung von Treffern / Wasserschüssen • Probleme und Sorgenkinder: • Skalierung des Spielfeldes für verschiedene Auflösungen • kein "Fullscreen" (Toolleiste über dem Spielfeld sichtbar)