Drucken

Bluetooth-Kommunikation

Mit Hilfe der Bluetooth-Kommunikation können Spiele, bei welchen zwei oder mehrere Personen gegeneinander spielen, programmiert werden. Sie setzt voraus, dass die Computer über eine Bluetooth-Schnittstelle verfügen. Dies ist in der Regel bei neueren Notebooks der Fall. Falls keine Bluetooth-Schnittstelle eingebaut ist, kann man einen externen USB-Bluetooth-Adapter verwenden. Unsere Applikationen verwenden die Bluetooth-Bibliothek von BlueCove (www.bluecove.org) mit einem darüber gelegten Klassen-Wrapper aus dem Package ch.aplu.bluetooth (www.aplu.ch/bluetooth).

Zu Beginn des Spieles bauen die beiden Spieler eine Bluetooth-Verbindung auf. Dabei muss der Bluetooth-Name des Partners bekannt sein. Unsere Spielprogramme fragen zuerst nach dem Bluetooth-Namen des Partners. Lässt man diesen leer und klickt "OK", so startet der Computer als Bluetooth-Server und zeigt in der Titelleiste den eigenen Bluetooth-Namen an. Gibt man einen Namen ein, so wird nach einem Bluetooth-Server mit diesem Namen gesucht. Wird er gefunden, so wird der Computer als Bluetooth-Client mit diesem Server verbunden, andernfalls wird automatisch ein Bluetooth-Server gestartet, der auf einen Client wartet. Normalerweise beginnt der Client mit dem ersten Spielzug und danach sind beide Partner abwechslungsweise am Zug.

 

 

Erster Computer: Bluetooth Server

 

  Zweiter Computer: Bluetooth Client

  In diesem einfachen Beispiel löscht der Spieler, der am Zug ist, jeweils mit einem Mausklick ein beliebiges Schiff. Dabei wird via Bluetooth ein Integer (x-Koordinate des gelöschten Schiffs) zum anderen Computer geschickt und dort das entprechende Schiff ebenfalls gelöscht. Nachher wird der Spieler in einen wartenden Zustand versetzt (Wait to play), während der andere Spieler einen Zug machen kann (It is you to play).

Programmcode:

// BtCom.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import ch.aplu.bluetooth.*;
import javax.swing.JOptionPane;

public class BtCom extends GameGrid
  implements GGMouseListener, BtPeerListener, GGExitListener
{
  private BluetoothPeer bp;
  private boolean isMyMove;
  private GGBackground bg;

  public BtCom()
  {
    super(10140Color.red, false);
    bg = getBg();
    init();
    show();
    addMouseListener(this, GGMouse.lClick);
    connect();
    addExitListener(this);
  }

  private void init()
  {
    bg.clear();
    for (int i = 0; i < 10; i++)
      addActor(new Ship()new Location(i, 0));
    refresh();
  }

  public boolean mouseEvent(GGMouse mouse)
  {
    if (!isMyMove)
      return true;
    Location loc = toLocationInGrid(mouse.getX(), mouse.getY());
    Actor actor = getOneActorAt(loc, Ship.class);
    if (actor != null)
    {
      actor.removeSelf();
      int[] data = new int[1];
      data[0] = actor.getLocation().x; // cell coordinate
      bp.sendDataBlock(data);
      refresh();
      isMyMove = false;
      setTitle("Wait to play");
    }
    return false;
  }

  private void connect()
  {
    String serverName;
    String prompt = "Enter Bluetooth Name";
    serverName = JOptionPane.showInputDialog(null, prompt, "");
    if (serverName == null)
      System.exit(0);
    serverName = serverName.trim();
    if (serverName.equals(""))
    {
      setTitle("Waiting as Server. Bluetooth Name: " + BluetoothFinder.getLocalBluetoothName());
      bp = new BluetoothPeer(serverName, "nim"thistrue);
    }
    else
    {
      setTitle("Connecting to " + serverName);
      bp = new BluetoothPeer(serverName, "nim"thistrue);
      if (bp.isConnected())
      {
        setTitle("Client connected, it is you to play");
        isMyMove = true// Client plays first 
      }
      else
        setTitle("Waiting as server. Bluetooth Name: " + BluetoothFinder.getLocalBluetoothName());
    }
  }

  public void notifyConnection(boolean connected)
  {
    System.out.println("Notify " + (connected ? "connected" : "connection lost"));
    if (connected)
    {
      setTitle("Server connected, wait to play");
      isMyMove = false;
    }
  }

  public void receiveDataBlock(int[] data)
  {
    int x = data[0];
    Location loc = new Location(x, 0);
    getOneActorAt(loc).removeSelf();
    isMyMove = true;
    setTitle("It is you to play");
    refresh();
  }

  public boolean notifyExit()
  {
    bp.releaseConnection();
    return true;
  }

  public static void main(String[] args)
  {
    new BtCom();
  }
}

// ----------------- class Ship ------------------
class Ship extends Actor
{
  public Ship()
  {
    super("sprites/boat.gif");
  }
}

Erklärungen zum Programmcode:
connect() Baut die Bluetooth-Verbindung auf. Zuerst wird der Bluetooth-Name des Partners abgefragt und nachher durch die Erstellung einer Instanz von BluetoothPeer die Verbindung eingeleitet
int[] data = new int[1]
data[0] = actor.getLocation().x
sendDataBlock(data)

Mit sendDataBlock(data) wird ein int-Array gesendet. In unserem Fall umfasst dieser einen einzigen Integer mit der Zellenkoordinate des entfernten Schiffs.

public void receiveDataBlock(int[] data)
{
    int x = data[0];
}

Die Methode receiveDataBlock() ist eine Callback-Methode des BtPeerListeners und wird aufgerufen, wenn der gesendete int-Array empfangen wird
init() Mit der Methode init() wird in jeder Zelle ein Schiff erzeugt
setTitle() Der aktueller Spielzustand wird im Titelbalken angezeigt
public boolean notifyExit ()
{
     bp. releaseConnection () ;
    return true ;
}
Durch Registrierung eines Exit-Listeners wird die normale Funktion des Close-Buttos im Tittelbalken aufgehoben und bewirkt, dass beim Klicken notifyExit() aufgerufen wird. Dadurch werden nötige Aufräumarbeiten (Unterbrechen der Bluetooth-Verbindung) ausgeführt. Der Rückgabe-Wert true bewirkt, dass das Programm nachfolgend beendet wird