📄 snakeview.cpp
字号:
// SnakeView.cpp : implementation of the CSnakeView class
//
#include "stdafx.h"
#include "Snake.h"
#include "MainFrm.h"
#include "SnakeDoc.h"
#include "SnakeView.h"
#include "ScoreBoardDlg.h"
#include "ChangeSpeedDlg.h"
#include <mmsystem.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define IDT_TIMER 1000
/////////////////////////////////////////////////////////////////////////////
// CSnakeView
IMPLEMENT_DYNCREATE(CSnakeView, CView)
BEGIN_MESSAGE_MAP(CSnakeView, CView)
//{{AFX_MSG_MAP(CSnakeView)
ON_WM_SIZE()
ON_WM_PAINT()
ON_WM_CONTEXTMENU()
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_TIMER()
ON_WM_KEYDOWN()
ON_WM_CLOSE()
ON_COMMAND(IDM_CHANGELEVEL, OnChangeLevel)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSnakeView construction/destruction
CSnakeView::CSnakeView()
: m_pDCMemDB(0),
m_pBmpDB(0),
m_pActionHandler(0),
m_numCellsX(10),
m_numCellsY(10),
m_timerID(0)
{
}
CSnakeView::~CSnakeView()
{
if (m_pDCMemDB)
delete m_pDCMemDB;
if (m_pBmpDB)
delete m_pBmpDB;
if (m_pActionHandler)
delete m_pActionHandler;
}
BOOL CSnakeView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CSnakeView drawing
void CSnakeView::OnDraw(CDC* pDC)
{
CSnakeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
m_pDC = pDC;
CRect rect;
GetClientRect(&rect);
// draw boundary
CBitmap bmpBrick;
bmpBrick.LoadBitmap(IDB_BRICK);
CBrush brBrick;
brBrick.CreatePatternBrush(&bmpBrick);
CBrush *pBrOld = pDC->SelectObject(&brBrick);
pDC->PatBlt(rect.left, rect.top,
rect.Width(), rect.Height(),
PATCOPY);
pDC->SelectObject(pBrOld);
// draw interior field
CBitmap bmpCell;
bmpCell.LoadBitmap(IDB_CELL);
CBrush brCell;
brCell.CreatePatternBrush(&bmpCell);
pBrOld = pDC->SelectObject(&brCell);
pDC->PatBlt(rect.left+32, rect.top+32+32,
rect.Width()-64, rect.Height()-64-32,
PATCOPY);
pDC->SelectObject(pBrOld);
// draw scoreboard
drawSprite(pDC, IDB_SCOREBOARD,
(int)((m_numCellsX-9)/2.0+1)*32, 5);
pDC->SetBkMode(TRANSPARENT);
pDC->TextOut((int)((m_numCellsX-9)/2.0+2)*32, 16,
"Scores:");
// draw all game components
if (m_pActionHandler)
m_pActionHandler->draw();
m_pDC = 0;
}
/////////////////////////////////////////////////////////////////////////////
// CSnakeView printing
BOOL CSnakeView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CSnakeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CSnakeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CSnakeView diagnostics
#ifdef _DEBUG
void CSnakeView::AssertValid() const
{
CView::AssertValid();
}
void CSnakeView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSnakeDoc* CSnakeView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSnakeDoc)));
return (CSnakeDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CSnakeView message handlers
void CSnakeView::OnInitialUpdate()
{
CView::OnInitialUpdate();
CClientDC dcClient(this);
OnPrepareDC(&dcClient);
m_pDCMemDB = new CDC;
m_pDCMemDB->CreateCompatibleDC(&dcClient);
m_pDCMemDB->SetMapMode(dcClient.GetMapMode());
}
void CSnakeView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
CRect rect;
GetClientRect(&rect); // device coordinates
// API without DC as arguments,
// always use device coordinates
if ((rect.right <= m_sizeDB.cx) &&
(rect.bottom <= m_sizeDB.cy)) return;
if (rect.right > m_sizeDB.cx)
m_sizeDB.cx = rect.right;
if (rect.bottom > m_sizeDB.cy)
m_sizeDB.cy = rect.bottom;
CClientDC dcClient(this);
OnPrepareDC(&dcClient); // order dependency: after adjustScrollSizes()
if (m_pBmpDB) delete m_pBmpDB;
m_pBmpDB = new CBitmap;
m_pBmpDB->CreateCompatibleBitmap(&dcClient, m_sizeDB.cx, m_sizeDB.cy);
}
void CSnakeView::OnPaint()
{
CPaintDC dc(this); // device context for painting
OnPrepareDC(&dc);
CBitmap *pBmpOld = m_pDCMemDB->SelectObject(m_pBmpDB);
CRect rectInvalid;
dc.GetClipBox(&rectInvalid); // logical coordinate
m_pDCMemDB->SelectClipRgn(NULL);
m_pDCMemDB->IntersectClipRect(&rectInvalid);
/*
CBrush brBackground((COLORREF)::GetSysColor(COLOR_WINDOW));
CBrush *pBrOld = m_pDCMemDB->SelectObject(&brBackground);
m_pDCMemDB->PatBlt(rectInvalid.left, rectInvalid.top,
rectInvalid.Width(), rectInvalid.Height(),
PATCOPY);
m_pDCMemDB->SelectObject(pBrOld);
*/
OnDraw(m_pDCMemDB);
dc.BitBlt(rectInvalid.left, rectInvalid.top,
rectInvalid.Width(), rectInvalid.Height(),
m_pDCMemDB, // MM_TEXT mode
rectInvalid.left, rectInvalid.top,
SRCCOPY);
m_pDCMemDB->SelectObject(pBmpOld);
}
void CSnakeView::drawSprite(CDC *pDC, int resID,
int ix, int iy)
{
BITMAP bmpInfo;
CSize sizeBmp;
CDC dcMem1, dcMem2;
dcMem1.CreateCompatibleDC(pDC);
dcMem2.CreateCompatibleDC(pDC);
// Step 1
// create mask step 1: XOR the specified color
CBitmap bmpSprite;
bmpSprite.LoadBitmap(resID);
bmpSprite.GetBitmap(&bmpInfo);
sizeBmp = CSize(bmpInfo.bmWidth, bmpInfo.bmHeight);
CBitmap bmpMask1;
bmpMask1.CreateCompatibleBitmap(pDC, bmpInfo.bmWidth, bmpInfo.bmHeight);
CBitmap *pOldBmp1 = (CBitmap *)dcMem1.SelectObject(&bmpMask1);
CPen *pPen = (CPen *) dcMem1.SelectStockObject(NULL_PEN);
CBrush br(RGB(131,0,0));
CBrush *pBr = (CBrush *)dcMem1.SelectObject(&br);
dcMem1.Rectangle(0,0,bmpInfo.bmWidth+1, bmpInfo.bmHeight+1);
dcMem1.SelectObject(pBr);
dcMem1.SelectObject(pPen);
CBitmap *pOldBmp2 = (CBitmap *)dcMem2.SelectObject(&bmpSprite);
// transparent color will now be black
dcMem1.SetMapMode(MM_TEXT); dcMem2.SetMapMode(MM_TEXT);
dcMem1.BitBlt(0, 0,
bmpInfo.bmWidth, bmpInfo.bmHeight,
&dcMem2,
0, 0, SRCINVERT);
dcMem1.SelectObject(pOldBmp1);
dcMem2.SelectObject(pOldBmp2);
// Step 2
// create mask step 2: make transparent color region white
CBitmap bmpMask2;
bmpMask2.CreateCompatibleBitmap(pDC, bmpInfo.bmWidth, bmpInfo.bmHeight);
pOldBmp2 = (CBitmap *)dcMem2.SelectObject(&bmpMask2);
pOldBmp1 = (CBitmap *)dcMem1.SelectObject(&bmpMask1);
dcMem1.SetMapMode(MM_TEXT); dcMem2.SetMapMode(MM_TEXT);
dcMem2.BitBlt(0, 0,
bmpInfo.bmWidth, bmpInfo.bmHeight,
&dcMem1,
0, 0, NOTSRCCOPY);
dcMem1.SelectObject(pOldBmp1);
dcMem2.SelectObject(pOldBmp2);
// Step 3
// create mask step 3: copy to Black-white bitmap so that
// nontransparent color region is black
CBitmap bmpBW1;
bmpBW1.CreateBitmap(bmpInfo.bmWidth, bmpInfo.bmHeight,1,1,0);
pOldBmp1 = (CBitmap *)dcMem1.SelectObject(&bmpBW1);
pOldBmp2 = (CBitmap *)dcMem2.SelectObject(&bmpMask2);
dcMem1.SetMapMode(MM_TEXT); dcMem2.SetMapMode(MM_TEXT);
dcMem1.BitBlt(0, 0,
bmpInfo.bmWidth, bmpInfo.bmHeight,
&dcMem2,
0, 0, SRCCOPY);
dcMem1.SelectObject(pOldBmp1);
dcMem2.SelectObject(pOldBmp2);
/*
// view the mask
dcMemMaskBW.SetMapMode(MM_LOENGLISH);
pOldBmp1 = (CBitmap *)dcMem1.SelectObject(&bmpBW1);
pDC->BitBlt(m_ptMouse.x-sizeBmp.cx/2, m_ptMouse.y-sizeBmp.cy/2,
sizeBmp.cx, sizeBmp.cy,
&dcMem1, // MM_LOENGLISH mode
0, 0, SRCCOPY);
dcMem1.SelectObject(pOldBmp1);
*/
// Step 4
// cut off the sprite from the background
bmpBW1.GetBitmap(&bmpInfo);
sizeBmp = CSize(bmpInfo.bmWidth, bmpInfo.bmHeight);
// both DC must be in the same mapping mode
// dcMem1.SetMapMode(MM_LOENGLISH);
pOldBmp1 = (CBitmap *)dcMem1.SelectObject(&bmpBW1);
pDC->BitBlt(ix, iy,
sizeBmp.cx, sizeBmp.cy,
&dcMem1, // MM_LOENGLISH mode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -