📄 view.cpp
字号:
// view.cpp
//
// Copyright (c) 2000 Symbian Ltd. All rights reserved.
#include "engine.h"
#include "view.h"
#include "controller.h"
#include <soloships.rsg>
#include <quartzkeys.h>
#include <gulutil.h>
#include <eikenv.h>
// fleet view
const TInt KTileSizeInTwips=480; // 1/3"
const TInt KBorderSizeInTwips=240; // 1/6"
const TInt KIdealBoardSizeInTwips=8*KTileSizeInTwips + 2*KBorderSizeInTwips; // 3"
void CFleetView::ConstructL(const TRect& aRect)
{
// window setup
CreateWindowL();
SetRect(aRect);
// set cursor
SetCursor(0,0);
// set zoom factor
SetZoomL(1000);
// activate control as ready for drawing
ActivateL();
}
CFleetView::~CFleetView()
{
iCoeEnv->ReleaseScreenFont(iTileFont);
iCoeEnv->ReleaseScreenFont(iBorderFont);
}
void CFleetView::SetController(TFleet& aFleet, MGameViewCmdHandler& aCmdHandler)
{
iCmdHandler=&aCmdHandler;
iFleet=&aFleet;
}
void CFleetView::SetZoomL(TInt aZoomFactor)
{
// check we're doing something useful
if (iZoomFactor==aZoomFactor)
return;
iZoomFactor=aZoomFactor;
// find available size in pixels
TInt boardSize=Rect().Width() < Rect().Height() ? Rect().Width() : Rect().Height();
// calculate board size in twips, and hence scale factor
TInt boardSizeInTwips=iCoeEnv->ScreenDevice()->HorizontalPixelsToTwips(boardSize);
boardSizeInTwips=(boardSizeInTwips * iZoomFactor) / 1000; // zoom
TInt scaleFactor=(boardSizeInTwips * 1000) / KIdealBoardSizeInTwips;
boardSize=iCoeEnv->ScreenDevice()->HorizontalTwipsToPixels(boardSizeInTwips);
// tile and border sizes also
TInt tileSizeInTwips=(KTileSizeInTwips*scaleFactor) / 1000;
TInt borderSizeInTwips=(KBorderSizeInTwips*scaleFactor) / 1000;
// calculate tile and border sizes in pixels, ensuring even distribution
iBorderSize=iCoeEnv->ScreenDevice()->HorizontalTwipsToPixels(borderSizeInTwips);
iTileSize=(boardSize-iBorderSize*2)/8; // eighth remaining, rounding down
TInt innerSize=iTileSize*8; // whole size of inner region
iBorderSize=(boardSize-innerSize)/2; // adjust border size again
boardSize=innerSize+iBorderSize*2; // final board size
// pre-calculate actual rectangles for everything
iTopBorder=TRect(0,0,boardSize,iBorderSize);
iBottomBorder=TRect(0,iBorderSize+innerSize,boardSize,boardSize);
iLeftBorder=TRect(0,iBorderSize,iBorderSize,iBorderSize+innerSize);
iRightBorder=TRect(iBorderSize+innerSize,iBorderSize,boardSize,iBorderSize+innerSize);
iBoardRect=TRect(iBorderSize,iBorderSize,iBorderSize+innerSize,iBorderSize+innerSize);
// offset everything to center properly
TPoint offset(
Rect().iTl.iX+(Rect().Width()-boardSize)/2,
Rect().iTl.iY+(Rect().Height()-boardSize)/2);
iTopBorder.Move(offset);
iBottomBorder.Move(offset);
iLeftBorder.Move(offset);
iRightBorder.Move(offset);
iBoardRect.Move(offset);
// get small font for drawing border
TFontSpec specBorder(_L("Arial"), (borderSizeInTwips*3)/4);
specBorder.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
CFont* borderFont=iCoeEnv->CreateScreenFontL(specBorder);
if (iBorderFont)
iCoeEnv->ReleaseScreenFont(iBorderFont);
iBorderFont=borderFont;
// larger font for drawing tiles
TFontSpec specTile(_L("Arial"), (tileSizeInTwips*3)/4);
specTile.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
CFont* tileFont=iCoeEnv->CreateScreenFontL(specTile);
if (iTileFont)
iCoeEnv->ReleaseScreenFont(iTileFont);
iTileFont=tileFont;
}
TInt CFleetView::GetZoom() const
{
return iZoomFactor;
}
// cursor
void CFleetView::SetCursorOff()
{
iCursorOn=EFalse;
}
void CFleetView::SetCursor(TInt aX, TInt aY)
{
iCursorOn=ETrue;
iCursorX=aX;
iCursorY=aY;
}
TBool CFleetView::CursorOn() const
{
return iCursorOn;
}
void CFleetView::GetCursor(TInt& aX, TInt& aY) const
{
aX=iCursorX;
aY=iCursorY;
}
// incremental drawing
void CFleetView::DrawTilesNow() const
{
Window().Invalidate(iBoardRect);
ActivateGc();
Window().BeginRedraw(iBoardRect);
DrawTiles();
Window().EndRedraw();
DeactivateGc();
}
// from CCoeControl
void CFleetView::Draw(const TRect&) const
{
DrawOutside();
DrawBorders();
DrawTiles();
}
TKeyResponse CFleetView::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
if (aType!=EEventKey)
return EKeyWasNotConsumed;
if (
aKeyEvent.iCode==EQuartzKeyFourWayLeft ||
aKeyEvent.iCode==EQuartzKeyFourWayRight ||
aKeyEvent.iCode==EQuartzKeyFourWayUp ||
aKeyEvent.iCode==EQuartzKeyFourWayDown
)
{
// move cursor
if (aKeyEvent.iCode==EQuartzKeyFourWayLeft)
MoveCursor(-1,0);
else if (aKeyEvent.iCode==EQuartzKeyFourWayRight)
MoveCursor(1,0);
else if (aKeyEvent.iCode==EQuartzKeyFourWayUp)
MoveCursor(0,-1);
else if (aKeyEvent.iCode==EQuartzKeyFourWayDown)
MoveCursor(0,1);
// redraw board
DrawTilesNow();
return EKeyWasConsumed;
}
else if (aKeyEvent.iCode==EQuartzKeyConfirm)
{
if (iFleet->IsKnown(iCursorX, iCursorY))
iEikonEnv->InfoMsg(R_GAME_ALREADY_KNOWN);
else
iCmdHandler->ViewCmdHitFleet(iCursorX, iCursorY);
return EKeyWasConsumed;
}
return EKeyWasNotConsumed;
}
void CFleetView::HandlePointerEventL(const TPointerEvent& aPointerEvent)
{
// check whether we're interested
if (
aPointerEvent.iType==TPointerEvent::EButton1Down &&
iBoardRect.Contains(aPointerEvent.iPosition)
)
{
// identify the tile that was hit
TInt x=(aPointerEvent.iPosition.iX-iBoardRect.iTl.iX)/iTileSize;
TInt y=(aPointerEvent.iPosition.iY-iBoardRect.iTl.iY)/iTileSize;
// move cursor if necessary
TBool iCursorMoved=(x!=iCursorX || y!=iCursorY);
SetCursor(x,y);
// hit square unless it's already known
if (iFleet->IsKnown(x,y))
{
iEikonEnv->InfoMsg(R_GAME_ALREADY_KNOWN);
if (iCursorMoved)
DrawTilesNow();
}
else
iCmdHandler->ViewCmdHitFleet(x,y);
}
}
// auxiliary drawing functions
void CFleetView::DrawOutside() const
{
CWindowGc& gc=SystemGc();
gc.SetPenStyle(CGraphicsContext::ENullPen);
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
gc.SetBrushColor(KRgbWhite);
DrawUtils::DrawBetweenRects(gc, Rect(), iBoardRect);
}
void CFleetView::DrawBorders() const
{
DrawHorizontalBorder(iTopBorder);
DrawHorizontalBorder(iBottomBorder);
DrawVerticalBorder(iLeftBorder);
DrawVerticalBorder(iRightBorder);
}
void CFleetView::DrawHorizontalBorder(const TRect& aRect) const
{
CWindowGc& gc = SystemGc();
// draw corners - in fact, whole border
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
gc.SetBrushColor(KRgbBlack);
gc.SetPenStyle(CGraphicsContext::ENullPen);
gc.DrawRect(aRect);
// draw letters
gc.SetPenStyle(CGraphicsContext::ESolidPen);
gc.SetPenColor(KRgbWhite);
_LIT(KBorderLetters,"ABCDEFGH");
gc.UseFont(iBorderFont);
for (TInt i=0; i<8; i++)
{
TRect rect(
aRect.iTl.iX+iBorderSize+i*iTileSize, aRect.iTl.iY,
aRect.iTl.iX+iBorderSize+(i+1)*iTileSize, aRect.iBr.iY
);
TPtrC text=KBorderLetters().Mid(i,1);
TInt baseline=rect.Height()/2 + iBorderFont->AscentInPixels()/2;
gc.DrawText(text, rect, baseline, CGraphicsContext::ECenter);
}
gc.DiscardFont();
}
void CFleetView::DrawVerticalBorder(const TRect& aRect) const
{
CWindowGc& gc = SystemGc();
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
gc.SetBrushColor(IsDimmed() ? KRgbGray : KRgbBlack);
gc.SetPenStyle(CGraphicsContext::ESolidPen);
gc.SetPenColor(KRgbWhite);
_LIT(KBorderLetters,"12345678");
gc.UseFont(iBorderFont);
for (TInt i=0; i<8; i++)
{
TRect rect(
aRect.iTl.iX, aRect.iTl.iY+i*iTileSize,
aRect.iBr.iX, aRect.iTl.iY+(i+1)*iTileSize
);
TPtrC text=KBorderLetters().Mid(i,1);
TInt baseline=rect.Height()/2 + iBorderFont->AscentInPixels()/2;
gc.DrawText(text, rect, baseline, CGraphicsContext::ECenter);
}
gc.DiscardFont();
}
void CFleetView::DrawTiles() const
{
CWindowGc& gc = SystemGc();
gc.UseFont(iTileFont);
for (TInt x=0; x<8; x++)
for (TInt y=0; y<8; y++)
DrawTile(x,y);
gc.DiscardFont();
}
void CFleetView::DrawTile(TInt aX, TInt aY) const
{
CWindowGc& gc = SystemGc();
TRect rect(
iBoardRect.iTl.iX+aX*iTileSize, iBoardRect.iTl.iY+aY*iTileSize,
iBoardRect.iTl.iX+(aX+1)*iTileSize, iBoardRect.iTl.iY+(aY+1)*iTileSize
);
// set background colour depending on whether known, hit or otherwise
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
if (!iFleet->IsKnown(aX,aY))
gc.SetBrushColor(KRgbWhite);
else if (iFleet->IsHit(aX,aY))
gc.SetBrushColor(KRgbDarkRed);
else gc.SetBrushColor(KRgbCyan);
// draw either plain square or text
if (iFleet->IsShip(aX,aY))
{
// set pen colour depending on whether hit or not
gc.SetPenStyle(CGraphicsContext::ESolidPen);
if (iFleet->IsHit(aX,aY))
gc.SetPenColor(KRgbYellow);
else
gc.SetPenColor(KRgbBlack);
// set character depending on ship and ship type
TPtrC text;
_LIT(kShips,"BCDF");
text.Set(kShips().Mid(iFleet->ShipType(aX,aY)-TShip::EBattleship,1));
// draw the square
TInt baseline=rect.Height()/2 + iTileFont->AscentInPixels()/2;
gc.DrawText(text, rect, baseline, CGraphicsContext::ECenter);
}
else // no ship
{
gc.SetPenStyle(CGraphicsContext::ENullPen);
gc.DrawRect(rect);
}
// special border if it's the cursor square
if (iCursorOn && aX==iCursorX && aY==iCursorY)
{
gc.SetPenStyle(CGraphicsContext::ESolidPen);
gc.SetBrushStyle(CGraphicsContext::ENullBrush);
gc.SetPenColor(KRgbBlack);
gc.DrawRect(rect);
rect.Shrink(1,1);
gc.SetPenColor(KRgbWhite);
gc.DrawRect(rect);
}
}
// cursor movement
void CFleetView::MoveCursor(TInt aDx, TInt aDy)
{
TInt x=iCursorX+aDx;
TInt y=iCursorY+aDy;
if (x<0 || x>=8 || y<0 || y>=8)
return;
iCursorX=x;
iCursorY=y;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -