?? controller.cpp
字號:
// controller.cpp
//
// Copyright (c) 2003 Symbian Ltd. All rights reserved.
//
#include "controller.h"
#include "view.h"
#include "appui.h"
#include <eikenv.h>
#include <eiklabel.h>
#include <s32mem.h>
enum TPanic {
EInitiateNotBlank,
EListenNotBlank,
ERestartNotFinished,
ESetGdpNotBlank,
ESetPrefBadState,
EHitFleetNotMyTurn,
EAbandonNotMyTurn,
EResendBadState,
EBindBadState,
ESendStartNoPrefs,
EHandleRequestBadOpcode,
EHandleResponseBadOpcode,
EHandleRestartReqNotFinished,
EHandleStartReqNotAccepting,
EHandleAbandondReqNotOppTurn,
EHandleHitReqNotOppTurn,
EHandleStartRespNotStarting,
EHandleHitRespNotOppTurn,
EHitFleetAlreadyKnown,
};
static void Panic(TInt aPanic)
{
_LIT(KPanicCategory,"BSHIPS-CTRL");
User::Panic(KPanicCategory, aPanic);
}
/*
class CGameController
*/
CGameController* CGameController::NewL()
{
CGameController* self=new(ELeave) CGameController;
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop();
return self;
}
CGameController* CGameController::NewL(const CStreamStore& aStore, TStreamId aStreamId)
{
CGameController* self=new(ELeave) CGameController;
CleanupStack::PushL(self);
self->RestoreL(aStore, aStreamId);
CleanupStack::Pop();
return self;
}
void CGameController::ConstructL()
{
iEnv=CEikonEnv::Static();
// construct engine and RGCP
iEngine=new(ELeave) CGameEngine;
iZoomFactor=1000;
iRgcp=new(ELeave) CRgcpSession;
iRgcp->ConstructL(KUidExample.iUid);
iRgcp->SetHandler(this);
}
void CGameController::SetAppView(CFleetView* aAppView)
{
iAppView=aAppView;
}
CGameController::~CGameController()
{
delete iEngine;
delete iRgcp;
}
// persistence
void CGameController::ExternalizeL(RWriteStream& aStream) const
{
aStream.WriteUint8L(iState);
aStream.WriteUint8L(iHaveFirstMovePref);
aStream.WriteUint8L(iFirstMovePref);
aStream.WriteInt32L(iZoomFactor);
}
void CGameController::InternalizeL(RReadStream& aStream)
{
iState=(TState) aStream.ReadUint8L();
iHaveFirstMovePref=aStream.ReadUint8L();
iFirstMovePref=(TFirstMovePref) aStream.ReadUint8L();
iZoomFactor=aStream.ReadInt32L();
}
TStreamId CGameController::StoreL(CStreamStore& aStore) const
{
RStoreWriteStream stream;
TStreamId id = stream.CreateLC(aStore);
iRgcp->ExternalizeL(stream);
iEngine->ExternalizeL(stream);
ExternalizeL(stream);
stream.CommitL();
CleanupStack::PopAndDestroy(); // stream
return id;
}
void CGameController::RestoreL(const CStreamStore& aStore, TStreamId aStreamId)
{
iEnv=CEikonEnv::Static();
RStoreReadStream stream;
stream.OpenLC(aStore,aStreamId);
// iRgcp=new(ELeave) CRgcpSession;
// iRgcp->ConstructL(KUidBattleShips.iUid);
// iRgcp->SetHandler(this);
iRgcp->InternalizeL(stream);
// iEngine=new(ELeave) CGameEngine;
iEngine->InternalizeL(stream);
InternalizeL(stream);
iGdpProtocol=iRgcp->Gsdp().GetGdpProtocol();
CleanupStack::PopAndDestroy(); // stream
}
// state
void CGameController::SetState(TState aState)
{
// update app view, if needed, for change in "my turn" status
if (iAppView)
{
if (Engine().IsMyTurn())
Engine().SetSecondPlayer();
else
Engine().SetFirstPlayer();
}
// set state as requested
iState=aState;
}
TInt CGameController::GetStateID()
{
switch(iState)
{
case EBlank : return 0;
break;
case EListening : return 1;
break;
case EInitiating : return 2;
break;
case EStarting : return 3;
break;
case EAccepting : return 4;
break;
case EMyTurn : return 5;
break;
case EOppTurn : return 6;
break;
case EFinished : return 7;
break;
case ERestarting : return 8;
break;
case EGameOn : return 9;
break;
default: return 0;
};
}
// game control
void CGameController::Reset() // set to blank, loopback, my-address from document
{
if (IsBlank())
return;
iEngine->Reset();
iRgcp->Terminate();
iRgcp->SetGdpProtocolL(KGdpLoopbackUid);
SetState(EBlank);
iHaveFirstMovePref=EFalse;
iEnv->InfoMsg(R_GAME_RESET);
}
void CGameController::SetGdpProtocolL(TUid aProtocol)
{
__ASSERT_ALWAYS(IsBlank(), Panic(ESetGdpNotBlank));
iRgcp->SetGdpProtocolL(aProtocol);
iGdpProtocol=aProtocol;
ActiveView().DrawNow(); //Should be Status view
}
void CGameController::SetFirstMovePref(TFirstMovePref aFirstMovePref)
{
__ASSERT_ALWAYS(IsBlank() || IsFinished() || IsRestarting(), Panic(ESetPrefBadState));
// store preferences
iFirstMovePref=aFirstMovePref;
iEngine->Reset();
iHaveFirstMovePref=ETrue;
// if finished, and in RGCP requesting, then send restart req and -> accepting
if (IsFinished() && Rgcp()->IsRequesting())
{
SendRestartRequest();
SetState(EAccepting);
}
// if restarting, then send start request and transition to starting
if (IsRestarting())
{
SendStartRequest();
SetState(EStarting);
}
ActiveView().DrawNow();
}
void CGameController::InitiateL(const TDesC& aOtherAddress)
{
__ASSERT_ALWAYS(IsBlank(), Panic(EInitiateNotBlank));
TBuf8<KMaxGsdpAddress> address;
address.Copy(aOtherAddress);
iRgcp->Initiate(address);
SetState(EInitiating);
ActiveView().DrawNow();
}
void CGameController::Listen()
{
__ASSERT_ALWAYS(IsBlank(), Panic(EListenNotBlank));
iRgcp->Listen();
SetState(EListening);
ActiveView().DrawNow();
}
void CGameController::Abandon()
{
__ASSERT_ALWAYS(IsMyTurn(), Panic(EAbandonNotMyTurn));
SendAbandonRequest();
SetState(EFinished);
iEnv->InfoMsg(R_GAME_ABANDONED);
ActiveView().DrawNow();
}
void CGameController::Resend()
{
__ASSERT_ALWAYS(Rgcp()->IsInitiating() || Rgcp()->IsWaiting(), Panic(EResendBadState));
iRgcp->Resend();
iEnv->InfoMsg(R_GAME_RESENT);
}
// query
TBool CGameController::HaveFirstMovePref() const
{
return iHaveFirstMovePref;
}
CGameController::TFirstMovePref CGameController::FirstMovePref() const
{
return iFirstMovePref;
}
CFleetView& CGameController::ActiveView() const
{
CGameAppUi* appUI = static_cast<CGameAppUi*>(iEnv->EikAppUi());
return appUI->ActiveView();
}
// MRgcpHandler stuff
void CGameController::RgcpHandleResponse(TInt aOpcode, const TDesC8& aData)
{
switch(aOpcode)
{
case KGameOpcodeStart:
HandleStartResponse(aData);
break;
case KGameOpcodeRestart:
break;
case KGameOpcodeNop:
break;
case KGameOpcodeAbandon:
break;
case KGameOpcodeHit:
HandleHitResponse(aData);
break;
case CRgcpSession::EReserved:
break;
default:
Panic(EHandleResponseBadOpcode);
}
}
void CGameController::RgcpHandleRequest(TInt aOpcode, const TDesC8& aData)
{
switch(aOpcode)
{
case KGameOpcodeStart:
HandleStartRequest(aData);
break;
case KGameOpcodeRestart:
HandleRestartRequest();
break;
case KGameOpcodeNop:
break;
case KGameOpcodeAbandon:
HandleAbandonRequest();
break;
case KGameOpcodeHit:
HandleHitRequest(aData);
break;
default:
Panic(EHandleRequestBadOpcode);
}
}
void CGameController::RgcpHandleTerminated(TBool aClientInitiated)
{
if (!aClientInitiated)
{
iEngine->Reset();
iRgcp->SetGdpProtocolL(KGdpLoopbackUid);
SetState(EBlank);
iHaveFirstMovePref=EFalse;
iEnv->InfoMsg(R_GAME_TERMINATED_BY_OPP);
}
}
void CGameController::RgcpHandleBound()
{
__ASSERT_ALWAYS(IsListening() || IsInitiating(), Panic(EBindBadState));
if (IsListening())
{
SendStartRequest();
SetState(EStarting);
}
if (IsInitiating())
SetState(EAccepting);
iEnv->InfoMsg(R_GAME_SESSION_BOUND);
ActiveView().DrawNow();
}
void CGameController::RgcpStartRequesting()
{
// if restarting, and have first-move prefs, then issue restart request
if (IsRestarting() && HaveFirstMovePref())
{
SendStartRequest();
SetState(EStarting);
ActiveView().DrawNow();
}
}
// fleet view commands
void CGameController::ViewCmdHitFleet(TInt aX, TInt aY)
{
if (IsMyTurn())
{
/// hit fleet
SendHitRequest(aX, aY);
/*switch (result)
{
case TFleet::EMiss:
break;
case TFleet::EShip:
ActiveView().ExplSound();
break;
case TFleet::ESunk:
ActiveView().SunkSound();
break;
case TFleet::EVoid:
break;
};*/
// update view and play sounds
ActiveView().DrawTilesNow();
SetState(EOppTurn);
}
else
{
iEnv->InfoMsg(R_GAME_NOT_YOUR_TURN);
}
}
void CGameController::SendRestartRequest()
{
iRgcp->SendRequest(KGameOpcodeRestart);
}
void CGameController::SendStartRequest()
{
__ASSERT_ALWAYS(iHaveFirstMovePref, Panic(ESendStartNoPrefs));
TBuf8<10> buffer;
RDesWriteStream writer(buffer);
writer.WriteUint8L(iFirstMovePref);
writer.CommitL();
iRgcp->SendRequest(KGameOpcodeStart, buffer);
}
void CGameController::SendAbandonRequest()
{
iRgcp->SendRequest(KGameOpcodeAbandon);
}
void CGameController::SendNopRequest()
{
iRgcp->SendRequest(KGameOpcodeNop);
}
void CGameController::SendHitRequest(TInt aX, TInt aY)
{
TBuf8<10> buffer;
RDesWriteStream writer(buffer);
writer.WriteUint8L(aX);
writer.WriteUint8L(aY);
writer.CommitL();
iRgcp->SendRequest(KGameOpcodeHit, buffer);
}
// sending responses
void CGameController::SendStartResponse(TBool iMeFirst)
{
TBuf8<10> buffer;
RDesWriteStream writer(buffer);
writer.WriteUint8L(!iMeFirst);
writer.CommitL();
iRgcp->SendResponse(KGameOpcodeStart, buffer);
}
void CGameController::SendHitResponse(TInt aX, TInt aY, TShip::TShipType aShipType)
{
TBuf8<10> buffer;
RDesWriteStream writer(buffer);
writer.WriteUint8L(aX);
writer.WriteUint8L(aY);
writer.WriteUint8L(aShipType);
writer.CommitL();
iRgcp->SendResponse(KGameOpcodeHit, buffer);
}
// handling requests
void CGameController::HandleRestartRequest()
{
__ASSERT_ALWAYS(IsFinished(), Panic(EHandleRestartReqNotFinished));
// transition to restarting
SetState(ERestarting);
}
void CGameController::HandleStartRequest(const TDesC8& aData)
{
__ASSERT_ALWAYS(IsAccepting(), Panic(EHandleStartReqNotAccepting));
// decide who has first turn - my preference prevails, and I get it if neither cares
RDesReadStream reader(aData);
TFirstMovePref otherPref=(TFirstMovePref) reader.ReadUint8L();
TBool meFirst=ETrue;
if (iFirstMovePref==EWantSecond)
meFirst=EFalse;
if (iFirstMovePref==EDontCare && otherPref==EWantFirst)
meFirst=EFalse;
// send start-response
SendStartResponse(meFirst);
// transition to either my-turn or opp-turn
if (meFirst)
SetState(EMyTurn);
else
SetState(EOppTurn);
// clear first move preferences
iHaveFirstMovePref=EFalse;
// if transition to opp-turn, send a nop-request
if (IsOppTurn())
SendNopRequest();
// update view
ActiveView().DrawNow();
}
void CGameController::HandleAbandonRequest()
{
//__ASSERT_ALWAYS(IsOppTurn(), Panic(EHandleAbandondReqNotOppTurn));
// transition to finished
SetState(EFinished);
// update view
ActiveView().DrawNow();
}
void CGameController::HandleHitRequest(const TDesC8& aData)
{
//__ASSERT_ALWAYS(IsOppTurn(), Panic(EHandleHitReqNotOppTurn));
// crack parameters
RDesReadStream reader(aData);
TInt x=reader.ReadUint8L();
TInt y=reader.ReadUint8L();
// hit the square
TFleet& fleet=iEngine->iMyFleet;
fleet.SetHit(x,y);
SendHitResponse(x,y,fleet.ShipType(x,y));
// update view
iAppView->SetCursor(x,y);
iAppView->DrawTilesNow();
// if game is lost, issue a nop-request and transition to finished
if (iEngine->IsLost())
{
SendNopRequest();
iEnv->InfoMsg(R_GAME_COMMISERATIONS);
SetState(EFinished);
}
else // transition to my-turn
SetState(EMyTurn);
// update view
ActiveView().DrawNow();
}
void CGameController::HandleStartResponse(const TDesC8& aData)
{
__ASSERT_ALWAYS(IsStarting(), Panic(EHandleStartRespNotStarting));
// transition to my-turn or opp-turn as appropriate
RDesReadStream reader(aData);
TBool meFirst=reader.ReadUint8L();
if (meFirst)
SetState(EMyTurn);
else
SetState(EOppTurn);
// clear first move preferences
iHaveFirstMovePref=EFalse;
// update view
ActiveView().DrawNow();
}
void CGameController::HandleHitResponse(const TDesC8& aData)
{
__ASSERT_ALWAYS(IsOppTurn(), Panic(EHandleHitRespNotOppTurn));
// crack parameters
RDesReadStream reader(aData);
TInt x=reader.ReadUint8L();
TInt y=reader.ReadUint8L();
TShip::TShipType type=(TShip::TShipType) reader.ReadUint8L();
// update engine
TFleet& fleet=iEngine->iOppFleet;
if (type==TShip::ESea)
{
fleet.SetSea(x,y);
ActiveView().MissSound();
}
else
{
fleet.SetShipType(x,y,type);
fleet.SetHit(x,y);
ActiveView().ExplSound();
}
// update view
iAppView->SetCursor(x,y);
iAppView->DrawTilesNow();
// if you won the game, transition to finished.
if (iEngine->IsWon())
{
SetState(EFinished);
iEnv->InfoMsg(R_GAME_CONGRATULATIONS);
}
// update view
iAppView->DrawNow();
}
// zooming
void CGameController::ZoomInL()
{
TInt zoom=iZoomFactor;
zoom=
zoom < 250 ? 250 :
zoom < 350 ? 350 :
zoom < 500 ? 500 :
zoom < 350 ? 350 :
zoom < 500 ? 500 :
zoom < 600 ? 600 :
zoom < 750 ? 750 :
zoom < 850 ? 850 :
zoom < 1000 ? 1000 :
250;
CGameAppUi* appUi = static_cast<CGameAppUi*>(iEnv->EikAppUi());
appUi->FleetViewData().SetZoomL(zoom);
ActiveView().DrawNow();
iZoomFactor=zoom;
}
void CGameController::ZoomOutL()
{
TInt zoom=iZoomFactor;
zoom=
zoom > 1000 ? 1000 :
zoom > 850 ? 850 :
zoom > 750 ? 750 :
zoom > 600 ? 600 :
zoom > 500 ? 500 :
zoom > 350 ? 350 :
zoom > 250 ? 250 :
1000;
CGameAppUi* appUi = static_cast<CGameAppUi*>(iEnv->EikAppUi());
appUi->FleetViewData().SetZoomL(zoom);
ActiveView().DrawNow();
iZoomFactor=zoom;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -