当前位置:首页 » 《随便一记》 » 正文

Visual C++实现俄罗斯方块游戏实战二:界面设计与实现(附源码和资源 可用于大作业)

18 人参与  2023年04月05日 17:42  分类 : 《随便一记》  评论

点击全文阅读


需要源码和资源请点赞关注收藏后评论区留言私信~~~

我们的Visual C++工程采用MFC框架模式,下面讲解各个功能模块的界面实现

一、游戏菜单的实现

可分为如下几个步骤

1:在工程资源中添加一个菜单资源

2:给每个菜单栏添加响应函数到CTertisView类中

3:菜单响应函数应该尽量调用类中的其他功能函数,减少直接处理的过程,这样程序代码阅读起来结构简单,功能明确,菜单响应函数代码如下

// TetrisView.cpp : implementation of the CTetrisView class//#include "stdafx.h"#include "Tetris.h"#include "TetrisDoc.h"#include "TetrisView.h"#include "HelpDlg.h"#include "HeroDlg.h"#include "LevelDlg.h"#include "Russia.h"#include <mmsystem.h>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/// CTetrisViewIMPLEMENT_DYNCREATE(CTetrisView, CView)BEGIN_MESSAGE_MAP(CTetrisView, CView)//{{AFX_MSG_MAP(CTetrisView)ON_COMMAND(IDR_ABOUT, OnAbout)ON_COMMAND(IDR_HERO_LIST, OnHeroList)ON_COMMAND(IDR_LEVEL_SETUP, OnLevelSetup)ON_COMMAND(IDR_PLAY_MUSIC, OnPlayMusic)ON_COMMAND(IDR_START_GAME, OnStartGame)ON_COMMAND(IDR_HELP, OnHelp)ON_WM_KEYDOWN()ON_WM_TIMER()//}}AFX_MSG_MAP// Standard printing commandsON_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()/// CTetrisView construction/destructionCTetrisView::CTetrisView(){m_bStart = FALSE;}CTetrisView::~CTetrisView(){}BOOL CTetrisView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying//  the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}/// CTetrisView drawingvoid CTetrisView::OnDraw(CDC* pDC){CTetrisDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);CDC Dc;if(Dc.CreateCompatibleDC(pDC)==FALSE)AfxMessageBox("Can't create DC");//没有开始,显示封面if( m_bStart){russia.DrawBK(pDC);}}/// CTetrisView printingBOOL CTetrisView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CTetrisView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add extra initialization before printing}void CTetrisView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: add cleanup after printing}/// CTetrisView diagnostics#ifdef _DEBUGvoid CTetrisView::AssertValid() const{CView::AssertValid();}void CTetrisView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CTetrisDoc* CTetrisView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTetrisDoc)));return (CTetrisDoc*)m_pDocument;}#endif //_DEBUG/// CTetrisView message handlersvoid CTetrisView::OnAbout() {CAboutDlg aboutDlg;//生成关于对话框aboutDlg.DoModal();//弹出关于对话框}void CTetrisView::OnHeroList() {CHeroDlg dlg;//生成英雄榜对话框dlg.DoModal();//弹出英雄榜对话框}void CTetrisView::OnLevelSetup() {CLevelDlgdlg;//生成等级设置对话框dlg.DoModal();//弹出等级设置对话框}void CTetrisView::OnPlayMusic() {CWnd*   pMain   =   AfxGetMainWnd();   CMenu*   pMenu   =   pMain->GetMenu();//判断播放音乐菜单当前状态BOOL bCheck = (BOOL)pMenu->GetMenuState(IDR_PLAY_MUSIC, MF_CHECKED);if(m_bStart){if(bCheck){pMenu->CheckMenuItem(IDR_PLAY_MUSIC, MF_BYCOMMAND | MF_UNCHECKED);}else{pMenu->CheckMenuItem(IDR_PLAY_MUSIC, MF_BYCOMMAND | MF_CHECKED);}PlayBackMusic(!bCheck);//调用播放背景音乐功能函数}}void CTetrisView::OnStartGame() {m_bStart = true;russia.GameStart();//调用RUSSIA对象的游戏开始函数SetTimer(1, russia.m_Speed, NULL);}void CTetrisView::OnHelp() {CHelpDlg dlg;//生成帮助对话框dlg.DoModal();//弹出对话框}void CTetrisView::PlayBackMusic(BOOL bCheck){//指定文件并播放if(bCheck){//播放音乐sndPlaySound("music.wav",SND_ASYNC); }else{//停止播放sndPlaySound(NULL,SND_PURGE); }}void CTetrisView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {//没有开始if(!m_bStart)return;switch(nChar){case VK_LEFT:russia.Move(KEY_LEFT);break;case VK_RIGHT:russia.Move(KEY_RIGHT);break;case VK_UP:russia.Move(KEY_UP);break;case VK_DOWN:russia.Move(KEY_DOWN);break;}//重画CDC* pDC=GetDC();russia.DrawBK(pDC);ReleaseDC(pDC);CView::OnKeyDown(nChar, nRepCnt, nFlags);}void CTetrisView::OnTimer(UINT nIDEvent) {//下移russia.Move(KEY_DOWN);//重画russia.DrawBK(GetDC());//关闭TIME1KillTimer(1);//调整速度SetTimer(1, russia.m_Speed, NULL);CView::OnTimer(nIDEvent);}

二、游戏帮助对话框的实现

创建一个对话框类,通过资源中的文字说明对游戏操作方法进行描述

#if !defined(AFX_HERODLG_H__6D0A81F3_A5F6_4816_899E_ACC62CDE229A__INCLUDED_)#define AFX_HERODLG_H__6D0A81F3_A5F6_4816_899E_ACC62CDE229A__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000// HeroDlg.h : header file///// CHeroDlg dialog// CHeroDlg dialogclass CHeroDlg : public CDialog{// Constructionpublic:void SetWriteFlg(BOOL bflg);CHeroDlg(CWnd* pParent = NULL);   // standard constructor// Dialog Data//{{AFX_DATA(CHeroDlg)enum { IDD = IDD_HERO_LIST };intm_level;CStringm_name;intm_score;//}}AFX_DATA// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CHeroDlg)public:virtual int DoModal();protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support//}}AFX_VIRTUAL// Implementationprotected:// Generated message map functions//{{AFX_MSG(CHeroDlg)virtual void OnOK();afx_msg void OnBtn();virtual BOOL OnInitDialog();//}}AFX_MSGDECLARE_MESSAGE_MAP()private:BOOL m_bWriteflg;};//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_HERODLG_H__6D0A81F3_A5F6_4816_899E_ACC62CDE229A__INCLUDED_)

类的实现比较简单,就是一个基本对话框类的结构,只对其中的知道了按钮响应函数进行实现,用于退出当前对话框

// HelpDlg.cpp : implementation file//#include "stdafx.h"#include "Tetris.h"#include "HelpDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/// CHelpDlg dialogCHelpDlg::CHelpDlg(CWnd* pParent /*=NULL*/): CDialog(CHelpDlg::IDD, pParent){//{{AFX_DATA_INIT(CHelpDlg)// NOTE: the ClassWizard will add member initialization here//}}AFX_DATA_INIT}void CHelpDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CHelpDlg)// NOTE: the ClassWizard will add DDX and DDV calls here//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CHelpDlg, CDialog)//{{AFX_MSG_MAP(CHelpDlg)//}}AFX_MSG_MAPEND_MESSAGE_MAP()/// CHelpDlg message handlersvoid CHelpDlg::OnOK() {// TODO: Add extra validation hereCDialog::OnOK();}

三、游戏英雄榜对话框的实现

要创建一个对话框资源和一个setup.ini配置文件,类声明如下

#if !defined(AFX_HELPDLG_H__A6CEBADE_794E_4F8C_85FB_311FC78558A3__INCLUDED_)#define AFX_HELPDLG_H__A6CEBADE_794E_4F8C_85FB_311FC78558A3__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000// HelpDlg.h : header file///// CHelpDlg dialogclass CHelpDlg : public CDialog{// Constructionpublic:CHelpDlg(CWnd* pParent = NULL);   // standard constructor// Dialog Data//{{AFX_DATA(CHelpDlg)enum { IDD = IDD_HELP };// NOTE: the ClassWizard will add data members here//}}AFX_DATA// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CHelpDlg)protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support//}}AFX_VIRTUAL// Implementationprotected:// Generated message map functions//{{AFX_MSG(CHelpDlg)virtual void OnOK();//}}AFX_MSGDECLARE_MESSAGE_MAP()};//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_HELPDLG_H__A6CEBADE_794E_4F8C_85FB_311FC78558A3__INCLUDED_)

类的实现中通过调用系统API函数对配置文件进行读写操作,而设置读写标志接口函数是对类中的一个成员变量进行赋值操作,达到写入或者读取的区分,代码如下

// HeroDlg.cpp : implementation file//#include "stdafx.h"#include "Tetris.h"#include "HeroDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/// CHeroDlg dialogCHeroDlg::CHeroDlg(CWnd* pParent /*=NULL*/): CDialog(CHeroDlg::IDD, pParent){m_bWriteflg = FALSE;}void CHeroDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CHeroDlg)DDX_Text(pDX, IDC_LEVEL_EDIT, m_level);DDX_Text(pDX, IDC_NAME_EDIT, m_name);DDX_Text(pDX, IDC_SCORE_EDIT, m_score);DDV_MinMaxInt(pDX, m_score, 0, 10000);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CHeroDlg, CDialog)//{{AFX_MSG_MAP(CHeroDlg)ON_BN_CLICKED(IDOK_BTN, OnBtn)//}}AFX_MSG_MAPEND_MESSAGE_MAP()/// CHeroDlg message handlersvoid CHeroDlg::OnOK() {}void CHeroDlg::SetWriteFlg(BOOL bflg){m_bWriteflg = bflg;}int CHeroDlg::DoModal() {char pszTmp[128] = {0};//读取配置文件GetPrivateProfileString("HERO", "name", "0", pszTmp, 127, ".\\setup.ini");m_name = CString(pszTmp);if(!m_bWriteflg){GetPrivateProfileString("HERO", "score", "0", pszTmp, 127, ".\\setup.ini");m_score = atoi(pszTmp);GetPrivateProfileString("HERO", "level", "0", pszTmp, 127, ".\\setup.ini");m_level = atoi(pszTmp);}return CDialog::DoModal();}void CHeroDlg::OnBtn() {UpdateData(TRUE);if(m_bWriteflg){CString tmp;tmp.Format("%d", m_score);WritePrivateProfileString("HERO", "name", m_name, ".\\setup.ini");WritePrivateProfileString("HERO", "score", tmp, ".\\setup.ini");tmp.Format("%d", m_level);WritePrivateProfileString("HERO", "level", tmp, ".\\setup.ini");}m_bWriteflg = FALSE;CDialog::OnOK();}BOOL CHeroDlg::OnInitDialog() {CDialog::OnInitDialog();if(m_bWriteflg){SetDlgItemText(IDOK_BTN, "记录");}return TRUE; }

四、游戏播放背景音乐的实现

播放游戏背景音乐,是通过调用Windows的API函数sndPlaySound来实现的,需要如下几个步骤

1:在工程文件中,添加winmm.lib静态库文件以及头文件

2:实现CTetrisView类中的PlayBackMusic成员函数

五、游戏等级设置对话框的实现

创建一个对话框资源,并往配置文件中添加一个小节用于记录设置游戏的等级,并且对确定按钮和取消按钮绑定响应函数,类的声明如下

#if !defined(AFX_LEVELDLG_H__E423F5C3_7698_4365_A009_4E6C7BC62189__INCLUDED_)#define AFX_LEVELDLG_H__E423F5C3_7698_4365_A009_4E6C7BC62189__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000// LevelDlg.h : header file///// CLevelDlg dialogclass CLevelDlg : public CDialog{// Constructionpublic:CLevelDlg(CWnd* pParent = NULL);   // standard constructor// Dialog Data//{{AFX_DATA(CLevelDlg)enum { IDD = IDD_LEVEL_DLG };intm_level;//}}AFX_DATA// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CLevelDlg)protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support//}}AFX_VIRTUAL// Implementationprotected:// Generated message map functions//{{AFX_MSG(CLevelDlg)virtual void OnOK();virtual void OnCancel();virtual BOOL OnInitDialog();//}}AFX_MSGDECLARE_MESSAGE_MAP()};//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_LEVELDLG_H__E423F5C3_7698_4365_A009_4E6C7BC62189__INCLUDED_)

游戏等级设置对话框通过初始化对话框时,把配置文件中的当前等级参数读出来并显示,然后根据用户单击确定按钮进行相应的写入操作,类的实现代码如下

// LevelDlg.cpp : implementation file//#include "stdafx.h"#include "Tetris.h"#include "LevelDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/// CLevelDlg dialogCLevelDlg::CLevelDlg(CWnd* pParent /*=NULL*/): CDialog(CLevelDlg::IDD, pParent){//{{AFX_DATA_INIT(CLevelDlg)m_level = 0;//}}AFX_DATA_INIT}void CLevelDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CLevelDlg)DDX_Text(pDX, IDC_LEVEL_EDIT, m_level);DDV_MinMaxInt(pDX, m_level, 1, 10);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CLevelDlg, CDialog)//{{AFX_MSG_MAP(CLevelDlg)//}}AFX_MSG_MAPEND_MESSAGE_MAP()/// CLevelDlg message handlersvoid CLevelDlg::OnOK() {if(UpdateData(TRUE)){CString tmp;tmp.Format("%d", m_level);WritePrivateProfileString("SETUP", "level", tmp, ".\\setup.ini");CDialog::OnOK();}}void CLevelDlg::OnCancel() {CDialog::OnCancel();}BOOL CLevelDlg::OnInitDialog() {CDialog::OnInitDialog();char pszTmp[128] = {0};GetPrivateProfileString("SETUP", "level", "0", pszTmp, 127, ".\\setup.ini");m_level = atoi(pszTmp);UpdateData(FALSE);return TRUE;  // return TRUE unless you set the focus to a control              // EXCEPTION: OCX Property Pages should return FALSE}

测试效果如下

 

 

 

创作不易 觉得有帮助请点赞关注收藏~~~


点击全文阅读


本文链接:http://zhangshiyu.com/post/58515.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1