📄 tcsgamedlg.cpp
字号:
// TcsGameDlg.cpp : implementation file
//
//BY 吴志刚 ewuzg@163.com,cn.fox@tom.com 2003//
#include "stdafx.h"
#include "TcsGame.h"
#include "TcsGameDlg.h"
#include "DlgVictory.h"
//Load Sound Lib//
#include <mmsystem.h>
#pragma comment(lib,"WINMM.LIB")
//==============================//
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnPaint();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
ON_WM_CTLCOLOR()
ON_WM_LBUTTONDOWN()
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTcsGameDlg dialog
CTcsGameDlg::CTcsGameDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTcsGameDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTcsGameDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDI_ICOSNAKE);
}
void CTcsGameDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTcsGameDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTcsGameDlg, CDialog)
//{{AFX_MSG_MAP(CTcsGameDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_KEYDOWN()
ON_WM_TIMER()
ON_COMMAND(IDM_START, OnStart)
ON_COMMAND(IDM_EXIT, OnExit)
ON_COMMAND(IDM_ABOUT, OnAbout)
ON_COMMAND(IDM_PAUSE, OnPause)
ON_WM_CTLCOLOR()
ON_COMMAND(IDM_SOUND, OnSound)
ON_COMMAND(IDM_THROUGH, OnThrough)
ON_COMMAND(IDM_STOP, OnStop)
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTcsGameDlg message handlers
BOOL CTcsGameDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
srand(GetTickCount());
////////////////////////init status bar//////////////////////////////
m_wndStatusBar.Create(WS_CHILD|WS_VISIBLE|CCS_BOTTOM,CRect(0,0,0,0),this,102);
int iPartDim[3]={80,370,-1};
m_wndStatusBar.SetParts(2,iPartDim);
m_wndStatusBar.SetText(_T("停止游戏"),0,0);
m_wndStatusBar.SetText(_T("方向键控制方向,P暂停,F2新游戏"),1,0);
///////////////////////////////////////////////////
pNumBmp[0].LoadBitmap(IDB_BMPN0);
pNumBmp[1].LoadBitmap(IDB_BMPN1);
pNumBmp[2].LoadBitmap(IDB_BMPN2);
pNumBmp[3].LoadBitmap(IDB_BMPN3);
pNumBmp[4].LoadBitmap(IDB_BMPN4);
pNumBmp[5].LoadBitmap(IDB_BMPN5);
pNumBmp[6].LoadBitmap(IDB_BMPN6);
pNumBmp[7].LoadBitmap(IDB_BMPN7);
pNumBmp[8].LoadBitmap(IDB_BMPN8);
pNumBmp[9].LoadBitmap(IDB_BMPN9);
pNumBmp[10].LoadBitmap(IDB_BMPNBLACK);
///////////////////////////////////////////////////
ClearArray();
m_nSnakeLen=0;
srand(GetTickCount());
m_nLenX=15;
m_nLenY=20;
m_nBlockLen=16;
m_nLevel=0;
m_nSnakeLife=5;
m_nTotalScore=0;
m_nTimeInterval=180;
m_bEnableSound=FALSE;
m_bCanThrough=FALSE;
m_bSnakeDied=TRUE;
m_nMaxLevel=10;
m_nWaitType=WAIT_NONE;
////////////////////////
m_nInitX=5;
m_nInitY=45;
m_rcGame.SetRect(m_nInitX,m_nInitY,m_nInitX+m_nLenX*m_nBlockLen,m_nInitY+m_nLenY*m_nBlockLen);
m_ptDisplay.x=m_rcGame.right+25;
m_ptDisplay.y=m_rcGame.top;
int nWx,nWy;
nWx=m_rcGame.left+((m_rcGame.right-m_rcGame.left)-180)/2;
nWy=m_rcGame.top+((m_rcGame.bottom-m_rcGame.top)-80)/2;
m_rcWait.SetRect(nWx,nWy,nWx+180,nWy+80);
///////////////////INIT TOOLBAR 256COLORS//////////////////////////////////
if (!m_wndToolBar.CreateEx(this, TBSTYLE_BUTTON, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_TOOLBAR1))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
//设置ToolBar的图标列表
m_ilTB.Create(32, 32, TRUE | ILC_COLOR8, 5, 0);
HICON hIcon = NULL;
hIcon = (HICON)::LoadImage(::AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICONNEW), IMAGE_ICON, 32, 32, 0);
m_ilTB.Add(hIcon);
hIcon = (HICON)::LoadImage(::AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICOPAUSE), IMAGE_ICON, 32, 32, 0);
m_ilTB.Add(hIcon);
hIcon = (HICON)::LoadImage(::AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICONSTOP), IMAGE_ICON, 32, 32, 0);
m_ilTB.Add(hIcon);
hIcon = (HICON)::LoadImage(::AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICOHELP), IMAGE_ICON, 32, 32, 0);
m_ilTB.Add(hIcon);
hIcon = (HICON)::LoadImage(::AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICONQUIT), IMAGE_ICON, 32, 32, 0);
m_ilTB.Add(hIcon);
m_wndToolBar.GetToolBarCtrl().SetImageList(&m_ilTB);
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
///////////////////////////////////////////////////////////////////////////
return TRUE; // return TRUE unless you set the focus to a control
}
void CTcsGameDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTcsGameDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
DrawGame();
DrawARNumber(m_nLevel, m_ptDisplay.x+6*13,m_ptDisplay.y+25);
DrawARNumber(m_nSnakeLen,m_ptDisplay.x+6*13,m_ptDisplay.y+23+50);
DrawARNumber(m_nTotalScore,m_ptDisplay.x+6*13,m_ptDisplay.y+46+75);
DrawLifeCount(m_nSnakeLife,m_ptDisplay.x,m_ptDisplay.y+69+60+30);
DrawInfoText();
DrawWait(m_nWaitType,m_nWaitCount);
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTcsGameDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CTcsGameDlg::DrawGame()
{
CBrush brush;
int i,j;
CRect rc;
CDC* pDC=GetDC();
brush.CreateSolidBrush(RGB(0,0,0));
pDC->FillRect(&m_rcGame,&brush);
rc.left=m_rcGame.left-3;
rc.right=m_rcGame.right+3;
rc.top=m_rcGame.top-3;
rc.bottom=m_rcGame.bottom+3;
//3D背景绘制
pDC->Draw3dRect(&rc,RGB(255,255,255),RGB(0,0,0));
pDC->DeleteDC();
brush.DeleteObject();
if(m_bSnakeDied)
{
for(i=0;i<m_nSnakeLen;i++)
DrawBlock(m_ptSnake[i].x,m_ptSnake[i].y,FALSE,TRUE);
}
else
{
for(i=0;i<m_nSnakeLen;i++)
DrawBlock(m_ptSnake[i].x,m_ptSnake[i].y,FALSE);
}
for(i=0;i<20;i++)
{
for(j=0;j<15;j++)
{
switch(m_nArray[i][j])
{
case TYPE_STONE:
DrawStone(j,i);
break;
case TYPE_FOOD:
DrawFood(j,i,TYPE_FOOD);
break;
case TYPE_AWARD:
DrawFood(j,i,TYPE_AWARD);
break;
}
}
}
}
//画“蛇”的一节
void CTcsGameDlg::DrawBlock(int ix, int iy,BOOL bErase,BOOL bDie)
{
CDC* pDC=GetDC();
CDC memDC;
CBrush brush;
CRect rcBlock;
if(bErase)//擦除
{
brush.CreateSolidBrush(RGB(0,0,0));
rcBlock.SetRect(ix*m_nBlockLen+m_nInitX,
iy*m_nBlockLen+m_nInitY,
ix*m_nBlockLen+m_nInitX+m_nBlockLen,
iy*m_nBlockLen+m_nInitY+m_nBlockLen);
pDC->FillRect(&rcBlock,&brush);
brush.DeleteObject();
}
else
{
CBitmap bitmap;
if(bDie)
bitmap.LoadBitmap(IDB_BITMAP5);
else
bitmap.LoadBitmap(IDB_BITMAP1);
memDC.CreateCompatibleDC(pDC);
memDC.SelectObject(bitmap);
pDC->BitBlt(ix*m_nBlockLen+m_nInitX,iy*m_nBlockLen+m_nInitY,
m_nBlockLen,m_nBlockLen,&memDC,0,0,SRCCOPY);
memDC.DeleteDC();
bitmap.DeleteObject();
}
pDC->DeleteDC();
}
//键盘接口
void CTcsGameDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)//1:down 2:Up 3:left 4:right
{
case VK_LEFT:
if((m_nCurDir!=4)&&(!m_bPause)&&(m_nCurDirTemp!=4))
{
m_nCurDir=3;
}
break;
case VK_RIGHT:
if((m_nCurDir!=3)&&(!m_bPause)&&(m_nCurDirTemp!=3))
{
m_nCurDir=4;
}
break;
case VK_DOWN:
if((m_nCurDir!=2)&&(!m_bPause)&&(m_nCurDirTemp!=2))
{
m_nCurDir=1;
}
break;
case VK_UP:
if((m_nCurDir!=1)&&(!m_bPause)&&(m_nCurDirTemp!=1))
{
m_nCurDir=2;
}
break;
case 'p':
case 'P':
OnPause();
break;
case VK_F2://新游戏
OnStart();
break;
}
//CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}
//映射键盘消息
BOOL CTcsGameDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message==WM_KEYDOWN)
{
OnKeyDown((UINT)pMsg->wParam,(UINT)pMsg->lParam,(UINT)pMsg->lParam);
return TRUE;
}
return CDialog::PreTranslateMessage(pMsg);
}
void CTcsGameDlg::AddSnakeLen(int indexX, int indexY)
{
int i;
for(i=m_nSnakeLen;i>0;i--)
m_ptSnake[i]=m_ptSnake[i-1];
m_ptSnake[0].x=indexX;
m_ptSnake[0].y=indexY;
m_nSnakeLen++;
}
//“移动”蛇
void CTcsGameDlg::MoveSnake(int nDir)
{
int i;
CPoint pt[25];
for(i=0;i<25;i++)
pt[i]=m_ptSnake[i];
switch(nDir)
{
case 1://down
m_ptSnake[0].y++;
m_ptSnake[0].y=m_ptSnake[0].y%20;
break;
case 2://up
m_ptSnake[0].y--;
if(m_ptSnake[0].y==-1)
m_ptSnake[0].y=19;
break;
case 3://left
m_ptSnake[0].x--;
if(m_ptSnake[0].x==-1)
m_ptSnake[0].x=14;
break;
case 4://right
m_ptSnake[0].x++;
m_ptSnake[0].x=m_ptSnake[0].x%15;
break;
}
if(m_nSnakeLen==1)
DrawBlock(pt[0].x,pt[0].y,TRUE);
if(m_nSnakeLen>=2)
{
DrawBlock(m_ptSnake[m_nSnakeLen-1].x,m_ptSnake[m_nSnakeLen-1].y,TRUE);
for(int i=1;i<m_nSnakeLen;i++)
{
m_ptSnake[i]=pt[i-1];
}
}
DrawBlock(m_ptSnake[0].x,m_ptSnake[0].y,FALSE);
}
//时间事件
void CTcsGameDlg::OnTimer(UINT nIDEvent)
{
if(nIDEvent==TIMER_NORMAL)
{//时钟用于蛇的运动
if(CheckDie())
{
KillTimer(1);
m_bSnakeDied=TRUE;
int i;
if(m_bEnableSound)
::PlaySound(MAKEINTRESOURCE(IDR_WAVDIE),AfxGetApp()->m_hInstance,SND_RESOURCE|SND_ASYNC);
for(i=0;i<m_nSnakeLen;i++)
DrawBlock(m_ptSnake[i].x,m_ptSnake[i].y,FALSE,TRUE);
m_nSnakeLife--;
if(m_nSnakeLife>=0)
{
DrawLifeCount(m_nSnakeLife,m_ptDisplay.x,m_ptDisplay.y+69+60+30);
SetTimer(TIMER_WAIT,200,NULL);
m_nWaitCount=1;
m_nWaitType=WAIT_DIED;
}
return;
}
if(CheckCanEat())
{
m_nTotalScore+=10;
DrawBlock(m_ptSnake[0].x,m_ptSnake[0].y,FALSE);
DrawARNumber(m_nSnakeLen,m_ptDisplay.x+6*13,m_ptDisplay.y+23+50);
DrawARNumber(m_nTotalScore,m_ptDisplay.x+6*13,m_ptDisplay.y+46+75);
if(m_bEnableSound)
::PlaySound(MAKEINTRESOURCE(IDR_WAVEAT),AfxGetApp()->m_hInstance,SND_RESOURCE|SND_ASYNC);
if(m_nSnakeLen==25)
{
KillTimer(1);
if(m_nLevel==m_nMaxLevel)
{
CDlgVictory dlg;
dlg.DoModal();
}
else
{
SetTimer(TIMER_WAIT,200,NULL);
m_nWaitCount=1;
m_nWaitType=WAIT_LEVUP;
}
}
else
{
CreateNewFood();
if((rand()%5)==0)
CreateNewFood(TYPE_AWARD);
if((rand()%25)==0)
CreateNewFood(TYPE_LIFE);
}
}
else
{
m_nCurDirTemp=m_nCurDir;
MoveSnake(m_nCurDir);
}
}//TIMER_NORMAL Events
else if(nIDEvent==TIMER_WAIT)
{//时钟:用于等待
DrawWait(m_nWaitType,m_nWaitCount%18);
m_nWaitCount++;
if(m_nWaitCount>18)
{
KillTimer(TIMER_WAIT);
if(m_nWaitType==WAIT_DIED)
{
ReDoLevel();
}
else if(m_nWaitType==WAIT_LEVUP)
{
m_nLevel++;
DoNextLevel();
}
m_nWaitType=WAIT_NONE;
}
}
CDialog::OnTimer(nIDEvent);
}
//开始新游戏
void CTcsGameDlg::OnStart()
{
m_nTotalScore=0;
m_nSnakeLife=5;
m_nSnakeLen=1;
m_nLevel=1;
m_bSnakeDied=FALSE;
if(m_bEnableSound)
::PlaySound(MAKEINTRESOURCE(IDR_WAVSTART),AfxGetApp()->m_hInstance,SND_RESOURCE|SND_ASYNC);
///////////////////////////////////////
m_ptSnake[0].x=7;
m_ptSnake[0].y=0;
m_nCurDir=1;//1:down 2:Up 3:left 4:right
m_nCurDirTemp=1;
////////////////////////////////////////
m_bPause=FALSE;
ClearArray();
SetLevel_00();
InvalidateRect(&m_rcGame,FALSE);
CreateNewFood();
////////////////////////////////////////
//关值
DrawARNumber(m_nLevel, m_ptDisplay.x+6*13,m_ptDisplay.y+25);
//长度
DrawARNumber(m_nSnakeLen,m_ptDisplay.x+6*13,m_ptDisplay.y+23+50);
//分数
DrawARNumber(m_nTotalScore,m_ptDisplay.x+6*13,m_ptDisplay.y+46+75);
//生命值
DrawLifeCount(m_nSnakeLife,m_ptDisplay.x,m_ptDisplay.y+69+60+30);
////////////////////////////////////////
m_nWaitType=WAIT_NONE;
m_wndStatusBar.SetText(_T("正在游戏"),0,0);
SetTimer(TIMER_NORMAL,m_nTimeInterval,NULL);
}
//清空矩阵
void CTcsGameDlg::ClearArray()
{
int i,j;
for(i=0;i<20;i++)
for(j=0;j<15;j++)
m_nArray[i][j]=TYPE_NULL;
}
//检查下一位置是否可“吃”
BOOL CTcsGameDlg::CheckCanEat()
{
int ix,iy;
switch(m_nCurDir)
{
case 1://down
ix=m_ptSnake[0].x;
iy=(m_ptSnake[0].y+1)%20;
break;
case 2://up
ix=m_ptSnake[0].x;
iy=m_ptSnake[0].y-1;
if(iy==-1)
iy=19;
break;
case 3://left
ix=m_ptSnake[0].x-1;
iy=m_ptSnake[0].y;
if(ix==-1)
ix=14;
break;
case 4://right
ix=(m_ptSnake[0].x+1)%15;
iy=m_ptSnake[0].y;
break;
}
if(m_nArray[iy][ix]==TYPE_FOOD)
{
m_nArray[iy][ix]=TYPE_NULL;
AddSnakeLen(ix,iy);
return TRUE;
}
else if(m_nArray[iy][ix]==TYPE_AWARD)
{
m_nArray[iy][ix]=TYPE_NULL;
m_nTotalScore+=10;
DrawARNumber(m_nTotalScore,m_ptDisplay.x+6*13,m_ptDisplay.y+46+75);
return FALSE;
}
else if(m_nArray[iy][ix]==TYPE_LIFE)
{
m_nArray[iy][ix]=TYPE_NULL;
m_nSnakeLife++;
DrawLifeCount(m_nSnakeLife,m_ptDisplay.x,m_ptDisplay.y+69+60+30);
return FALSE;
}
return FALSE;
}
//产生新的"食物",要排除"蛇"和障碍物已占有的位置
void CTcsGameDlg::CreateNewFood(int nFoodType)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -