📄 bluetoothmanager.cpp
字号:
// Copyright (c) Symbian Ltd 2008. All rights reserved.
#include "rpsgamescreens.h"
#include "BluetoothManager.h"
#include "BluetoothDeviceDiscoverer.h"
#include "BluetoothConnector.h"
#include "common.hrh"
// -----------------------------------------------------------------------------------
// CBluetoothManager class
// -----------------------------------------------------------------------------------
CBluetoothManager* CBluetoothManager::NewL(CGameScreenManager& aGameScreenMgr)
{
CBluetoothManager* me = new (ELeave) CBluetoothManager(aGameScreenMgr);
CleanupStack::PushL(me);
me->ConstructL();
CleanupStack::Pop(me);
return (me);
}
void CBluetoothManager::ConstructL()
{
// Get socket server session
User::LeaveIfError(iSocketServer.Connect());
iBtDeviceDiscoverer = CBluetoothDeviceDiscoverer::NewL(*this);
}
CBluetoothManager::CBluetoothManager(CGameScreenManager& aGameScreenMgr)
: iGameScreenMgr(aGameScreenMgr)
{
TUUID targetServiceClass(KRPS_BTServiceID);
//Use by the RNotifier dialog to get only BT devices that supports the RPS's service
iDevSelFilter.SetUUID(targetServiceClass);
}
CBluetoothManager::~CBluetoothManager()
{
if(iBtConnBase)
{
iBtConnBase->Cancel();
delete iBtConnBase;
}
if (iBtDeviceDiscoverer)
{
iBtDeviceDiscoverer->Cancel();
delete iBtDeviceDiscoverer;
}
iSocketServer.Close();
//iBtConnBaseArray.ResetAndDestroy();//Not used for 2 player multiplay, see header file for details
}
/*
============================================================================
Callback from the Control Screen. The player has decided to control the game.
The CRpsGameEngine takes the Master role of the game.
============================================================================
*/
void CBluetoothManager::StartBtMaster()
{
iGameScreenMgr.GameData().iRpsError = KErrNone;
//Display the Connecting screen
iGameScreenMgr.SetGameState(CGameScreenManager::ENotifierScreen);
//Start BT device discovery
TBTDeviceSelectionParamsPckg pckg(iDevSelFilter);
TRAPD(err, iBtDeviceDiscoverer->DiscoverAndSelectDeviceL(pckg));
if(err!=KErrNone)
{
DisplayError(err);
}
}
/*
============================================================================
Callback from the Control Screen. The player has decided to wait for a connection.
The CRpsGameEngine takes the Slave role of the game.
============================================================================
*/
void CBluetoothManager::StartBtSlave()
{
iGameScreenMgr.GameData().iRpsError = KErrNone;
//Display the Waiting Screen
iGameScreenMgr.SetGameState(CGameScreenManager::EWaitConnScreen);
ASSERT(!iBtConnBase);
TRAPD(err, iBtConnBase = CBluetoothResponder::NewL(*this, iSocketServer);
iBtConnBase->StartL());
if(err != KErrNone)
{
if(iBtConnBase)
{
delete iBtConnBase;
iBtConnBase = NULL;
}
DisplayError(err);
}
}
/*
============================================================================
Quit the game either because the player decided to exit the game (KErrNone)
or because an error occurred during the game
============================================================================
*/
void CBluetoothManager::QuitMultiplayerGame()
{
iConnected = EFalse;
if(iBtConnBase)
{
iBtConnBase->Cancel();
delete iBtConnBase;
iBtConnBase = NULL;
}
}
/*
============================================================================
Master kick off the game.
============================================================================
*/
void CBluetoothManager::StartGame()
{
//We assume only the Master can start the game since it's the one that controls the game.
ASSERT(iBtConnBase);
ASSERT(iBtConnBase->Master());
if(iConnected)
{
//Send the control flag EPlay to the slave asking to start the game
TPckgBuf<TRpsData> rpsData;
rpsData().iRpsControl = TRpsData::EPlay;
iBtConnBase->SendData(rpsData);
// Reset the game data before play starts
iGameScreenMgr.Roshambo().ResetPlayers();
//Show the play screen
iGameScreenMgr.SetGameState(CGameScreenManager::EPlayScreen);
}
}
/*
============================================================================
Start another session of the game.
============================================================================
*/
void CBluetoothManager::ReplayGame()
{
//Master and Slave restart the game
ASSERT(iBtConnBase);
if(iConnected)
{
if(iBtConnBase->Master())
{
//Master displays the Start Screen
iGameScreenMgr.SetGameState(CGameScreenManager::EStartScreen);
}
else
{
//Slave displays the Wait Start Screen
iGameScreenMgr.SetGameState(CGameScreenManager::EWaitStartScreen);
}
}
}
/*
============================================================================
Send the RPS's player choice to the remote BT device. On completion calls SendDataComplete()
============================================================================
*/
void CBluetoothManager::SendData(TRoshambo::TElement aElement)
{
//Note that the code here to send the data to the remote device is the same for the
//Master and slave. Change the code to be like ReplayGame() above if your multiplayer game needs to handle
//the Master and Slave differently.
if(iConnected)
{
TPckgBuf<TRpsData> rpsData;
rpsData().iElement = aElement;
rpsData().iRpsControl = TRpsData::EElement;
//Since the sending is an asynchronous operation we need to cache the local player's choice
iGameScreenMgr.Roshambo().SetLocalPlayer(aElement);
// Now wait for the opponent to choose
iGameScreenMgr.SetGameState(CGameScreenManager::EWaitOpponentScreen);
iBtConnBase->SendData(rpsData);
}
}
/*
============================================================================
Query function to see if Master/Slave are connected
============================================================================
*/
TBool CBluetoothManager::Connected()
{
return iConnected;
}
/*
============================================================================
RNotifier's callback. aResponse contains the player's selected BT device
============================================================================
*/
void CBluetoothManager::OnDeviceDiscoveryComplete(const TBTDeviceResponseParamsPckg& aResponse)
{
iGameScreenMgr.SetGameState(CGameScreenManager::EConnectingScreen);
iBtDevAddr = aResponse().BDAddr();
if(iBtConnBase)
{
iBtConnBase->Cancel();
delete iBtConnBase;
iBtConnBase = NULL;
}
//It's important to note that in a multiplayer game with more then two players, the engine needs to create an
//array of iBtConnBase, one for each Master<->Slave connection in the BT piconet. The BT piconet contains
//the BT devices (Slaves) selected by the player (Master). RHostResolver needs to be use instead of RNotifier
//if your application needs to select more then two BT devices at one time. A customized UI needs also to be
//implemented to show the player and the available BT devices (s)he can select.The engine needs also to manage
//the bidirectional communication between the Master<->Slaves and SlaveN<->Master<->SlaveM.
TRAPD(err, StartConnectorL());
if(err != KErrNone)
{
delete iBtConnBase;
iBtConnBase = NULL;
DisplayError(err);
}
}
void CBluetoothManager::StartConnectorL()
{
iBtConnBase = CBluetoothConnector::NewL(*this, iSocketServer, iBtDevAddr);
iBtConnBase->StartL();
}
/*
============================================================================
Callback from CBluetoothDeviceDiscoverer if an error occur during device discovery
============================================================================
*/
void CBluetoothManager::OnDeviceDiscoveryErr(const TInt aError)
{
DisplayError(aError);
}
/*
============================================================================
Callback either from the Connector or Responder to report a connection error
============================================================================
*/
void CBluetoothManager::ConnectionErr(const TInt /*aConnHandle*/, const TInt aError)
{
//See RpsGameEngine.h to see how your multiplayer game could use aConnHandle
if(aError == KErrNone)
{
//KErrNone means succesful connection
iConnected = ETrue;
//Master and Slave need to take different action at this point
ASSERT(iBtConnBase);
if(iBtConnBase->Master())
{
iGameScreenMgr.SetGameState(CGameScreenManager::EStartScreen);
}
else
{
iGameScreenMgr.SetGameState(CGameScreenManager::EWaitStartScreen);
}
}
else
{
QuitMultiplayerGame();
DisplayError(aError);
}
}
/*
============================================================================
Callback either from the Connector or Responder to report incoming data from the remote BT device
============================================================================
*/
void CBluetoothManager::DataReceived(const TInt /*aConnHandle*/, const TDesC8& aData)
{
//See RpsGameEngine.h to see how your multiplayer game could use aConnHandle
TPckgBuf<TRpsData> rpsData;
rpsData.Copy(aData);
if(rpsData().iRpsControl == TRpsData::EPlay)
{
//We assume that only the Responder deals with game's control flags.
ASSERT(!iBtConnBase->Master());
iGameScreenMgr.Roshambo().ResetPlayers();
//Start the game by displaying the Play Screen
iGameScreenMgr.SetGameState(CGameScreenManager::EPlayScreen);
}
else if(rpsData().iRpsControl == TRpsData::EElement)
{
TPckgBuf<TRpsData> rpsData;
rpsData.Copy(aData);
if(iGameScreenMgr.Roshambo().LocalPlayer() != TRoshambo::EInvalid)
{
//Player already sent the rps's element, display the result.
iGameScreenMgr.Roshambo().SetOpponent(rpsData().iElement);
iGameScreenMgr.SetGameState(CGameScreenManager::EResultScreen);
}
else
{
//Cache the opponent element and wait for the player
iGameScreenMgr.Roshambo().SetOpponent(rpsData().iElement);
}
}
}
/*
============================================================================
Callback either from the Connector or Responder to report the sending data completion
============================================================================
*/
void CBluetoothManager::SendDataComplete(const TInt /*aConnHandle*/)
{
//See RpsGameEngine.h to see how your multiplayer game could use aConnHandle
//We already cached the local player's move
if(iGameScreenMgr.Roshambo().Opponent() != TRoshambo::EInvalid)
{
//Opponent already submitted the move, so result can be calculated and displayed
iGameScreenMgr.SetGameState(CGameScreenManager::EResultScreen);
}
}
void CBluetoothManager::DisplayError(TInt aError)
{
iGameScreenMgr.GameData().iRpsError = aError;
iGameScreenMgr.SetGameState(CGameScreenManager::EErrorScreen);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -