MFC 小游戏之贪吃蛇
来源:互联网 发布:网络发票验旧系统 编辑:程序博客网 时间:2024/04/29 19:44
弄了控制台的贪吃蛇等游戏后,学了一些MFC,即马上去弄MFC的贪吃蛇。写的时候由于学的MFC视频和实际操作还是有很大区别的,很多东西还是要自己去查MSDN或百度才知道的,在这里次MFC贪吃蛇中学到了很多知识!做出来后发现界面有闪烁的显现,后有前辈说可以采取双缓冲去避免闪烁,即百度查了不少这方面的资料,自己编写后还是闪烁,后问前辈是否写错,前辈说未写错,我就继续找度娘,找了很久没弄出来,最后就去csdn论坛去发了个帖子。呵,果然给力,一下解决了问题。即只要添加一个消息函数OnEraseBkgnd(CDC* pDC) 在加上之前的双缓冲即可避免不闪烁了!很是高兴啊!
关于双缓冲 和 OnEraseBkgnd(CDC* pDC) 的资料请看我博客的文章。
我是用VC6建立一个.exe
大家可以交流下,如有不好之处,请见谅!
// mfc_snackeView.cpp : implementation of the CMfc_snackeView class//#include "stdafx.h"#include "mfc_snacke.h"#include "mfc_snackeDoc.h"#include "mfc_snackeView.h"#include <cstdlib>#include <ctime>#include <cmath>#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CMfc_snackeViewIMPLEMENT_DYNCREATE(CMfc_snackeView, CView)BEGIN_MESSAGE_MAP(CMfc_snackeView, CView) //{{AFX_MSG_MAP(CMfc_snackeView) ON_WM_TIMER() ON_WM_KEYDOWN() ON_COMMAND(IDS_EASY, OnEasy) ON_COMMAND(IDS_MEDIUM, OnMedium) ON_COMMAND(IDS_HARD, OnHard) ON_WM_ERASEBKGND() //}}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()/////////////////////////////////////////////////////////////////////////////// CMfc_snackeView construction/destructionCMfc_snackeView::CMfc_snackeView(){ // TODO: add construction code here m_Count = m_UseTime = 0; m_start = 0; //记录玩家开始第几次玩 m_speed = 500; //初始化速度为0.5s H = 35; //地图的high 和 length,实际x = (40,580), y = (40, 380) L = 55; //这样主要是为了rand的方便 srand(time(0)); //随机种子 CMfc_snackeView::Initial_Game(); //初始化游戏的界面}CMfc_snackeView::~CMfc_snackeView(){}BOOL CMfc_snackeView::PreCreateWindow(CREATESTRUCT& cs){ // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CMfc_snackeView drawingvoid CMfc_snackeView::OnDraw(CDC* pDC) //画界面{ CMfc_snackeDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); ////////////////////////////////////////////////////////////////////////// CDC MemDC; //首先定义一个显示设备对象 CBitmap MemBitmap; //定义一个位图对象 //随后建立与屏幕显示兼容的内存显示设备 MemDC.CreateCompatibleDC(pDC); //这时还不能绘图,因为没有地方画 //下面建立一个于屏幕显示兼容的位图,至于位图的大小嘛 //可以用窗口的大小 CRect rect; GetClientRect(&rect); MemBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()); //将位图选入到内存显示设备中 //只要有选入了位图的内存显示设备才有地方地方绘图,画到指定的位图上 CBitmap *pOldBit = MemDC.SelectObject(&MemBitmap); //先用背景色将位图清除干净,这里我用的是白色作为背景 //你也可以用自己应该用的颜色 MemDC.FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(255, 255, 255)); //绘图////////////////////////////////////////////////////////////////////////// //draw border of game MemDC.Rectangle(CRect(39, 39, 601, 401)); //Records cstring show CString s; s.Format("当前用时: %d", m_UseTime/(1000/m_speed)); MemDC.TextOut(620, 60, s); s.Format("当前得分: %d", m_Count); MemDC.TextOut(620, 100, s); s.Format("版权所有: [菜菜]咸鱼"); MemDC.TextOut(620, 140, s); s.Format("时间: 2011-10-22"); MemDC.TextOut(620, 180, s); //draw snake //draw head of snake CPoint h; h = m_body.GetAt(0); MemDC.SelectStockObject(DKGRAY_BRUSH); switch(m_NowDir) { case 4: MemDC.Pie(CRect(h.x, h.y, h.x+20, h.y+20), CPoint(h.x+5, h.y), CPoint(h.x+15, h.y)); MemDC.SelectStockObject(WHITE_BRUSH ); //蛇的眼睛 MemDC.Ellipse(h.x+13, h.y+5, h.x+18, h.y+10); break; case 3: MemDC.Pie(CRect(h.x, h.y, h.x+20, h.y+20), CPoint(h.x+20, h.y+5), CPoint(h.x+20, h.y+15)); MemDC.SelectStockObject(WHITE_BRUSH ); MemDC.Ellipse(h.x+10, h.y+2, h.x+15, h.y+7); break; case 2: MemDC.Pie(CRect(h.x, h.y, h.x+20, h.y+20), CPoint(h.x+15, h.y+20), CPoint(h.x+5, h.y+20)); MemDC.SelectStockObject(WHITE_BRUSH ); MemDC.Ellipse(h.x+13, h.y+10, h.x+18, h.y+15); break; case 1: MemDC.Pie(CRect(h.x, h.y, h.x+20, h.y+20), CPoint(h.x, h.y+15), CPoint(h.x, h.y+5)); MemDC.SelectStockObject(WHITE_BRUSH ); MemDC.Ellipse(h.x+5, h.y+2, h.x+10, h.y+7); break; } //draw body of snake CPoint b; MemDC.SelectStockObject(GRAY_BRUSH); for(int i = 1; i <= m_body.GetUpperBound(); i++) { b = m_body.GetAt(i); MemDC.Rectangle(CRect(b.x, b.y, b.x+20, b.y+20)); } //draw a food CBrush br; br.CreateSolidBrush(RGB(0, 255, 0)); MemDC.SelectObject(br); MemDC.FillRect(CRect(m_food.x, m_food.y, m_food.x+20, m_food.y+20), &br); MemDC.Rectangle(CRect(m_food.x, m_food.y, m_food.x+20, m_food.y+20)); //将内存中图拷贝到屏幕上进行显示 pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY); //绘图完成后的清理 MemBitmap.DeleteObject(); MemDC.DeleteDC();}/////////////////////////////////////////////////////////////////////////////// CMfc_snackeView printingBOOL CMfc_snackeView::OnPreparePrinting(CPrintInfo* pInfo){ // default preparation return DoPreparePrinting(pInfo);}void CMfc_snackeView::OnBeginPrinting(CDC* , CPrintInfo* ){ // TODO: add extra initialization before printing}void CMfc_snackeView::OnEndPrinting(CDC* , CPrintInfo* ){ // TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CMfc_snackeView diagnostics#ifdef _DEBUGvoid CMfc_snackeView::AssertValid() const{ CView::AssertValid();}void CMfc_snackeView::Dump(CDumpContext& dc) const{ CView::Dump(dc);}CMfc_snackeDoc* CMfc_snackeView::GetDocument() // non-debug version is inline{ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMfc_snackeDoc))); return (CMfc_snackeDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CMfc_snackeView message handlersvoid CMfc_snackeView::Initial_Game() //游戏地图的初始化{ m_body.RemoveAll(); //initial direciton m_NowDir = m_PreDir = 3; //inital head of snake CPoint head; head.x = 100; head.y = 100; m_body.Add(head); //create rand food CMfc_snackeView::Create_food();}void CMfc_snackeView::Create_food(){ CPoint t; int x, y, prove; while(1) { x = rand()%L + 4; y = rand()%H + 4; if(x%2 == 0 && y%2 == 0) //其实坐标是x=(40,580), y=(40,380) { //每一个图标如蛇头的high和length是占20, 20 prove = 0; x *= 10; y *= 10; //食物不能是蛇的地方 for(int i = 0; i <= m_body.GetUpperBound(); i++) { t = m_body.GetAt(i); if(t.x == x && t.y == y) { prove = 1; break; } } if(!prove) break; } } m_food = CPoint(x, y);}void CMfc_snackeView::GameStart() //开始游戏哦{ //玩家时间和得分数的初始化 m_Count = m_UseTime = 0; m_start++; if(m_start > 1) CMfc_snackeView::Initial_Game(); //每隔m_speed时间发送WM_TIMER消息 Timer = SetTimer(1, m_speed, NULL);}void CMfc_snackeView::OnTimer(UINT nIDEvent) //WM_TIMER消息{ // TODO: Add your message handler code here and/or call default m_UseTime++; //时间记录 //蛇移动 CMfc_snackeView::Move(); CView::OnTimer(nIDEvent);}void CMfc_snackeView::Move() //蛇移动函数{ if(m_PreDir == m_NowDir || abs(m_PreDir-m_NowDir) == 2) m_NowDir = m_PreDir; else m_PreDir = m_NowDir; CPoint head; head = m_body.GetAt(0); //4个方向 switch(m_NowDir) { case 4: head.y -= 20; break; case 3: head.x += 20; break; case 2: head.y += 20; break; case 1: head.x -= 20; break; } int over = 0; CPoint t; //蛇头是否吃到自己 for(int i = 0; i <= m_body.GetUpperBound(); i++) { t = m_body.GetAt(i); if(head.x == t.x && head.y == t.y) { over = 1; break; } } if(!Check(head) || over) { //结束Timer,并弹出一个结束的对话框 KillTimer(Timer); MessageBox("Game is over! You are fail!"); } else { m_body.InsertAt(0, head); //蛇头吃到食物 if(head.x == m_food.x && head.y == m_food.y) { m_Count++; Create_food(); } else m_body.RemoveAt(m_body.GetUpperBound()); } //使整个窗口客户区无效,意味着需要重绘,即调用OnDraw函数 //InvalidateRect(CRect(39, 39, 839, 489)); Invalidate();}//键盘按键判断void CMfc_snackeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){ // TODO: Add your message handler code here and/or call default if(m_start) { switch(nChar) { case 38: //up m_NowDir = 4; break; case 39: //right m_NowDir = 3; break; case 40: //down m_NowDir = 2; break; case 37: //left m_NowDir = 1; break; default: m_NowDir = m_PreDir; break; } } CView::OnKeyDown(nChar, nRepCnt, nFlags);}//判断是否出界int CMfc_snackeView::Check(CPoint head){ if(head.x < 40 || head.x > 580 || head.y < 40 || head.y > 380) return 0; else return 1;}void CMfc_snackeView::OnEasy(){ // TODO: Add your command handler code here m_speed = 500; CMfc_snackeView::GameStart();}void CMfc_snackeView::OnMedium(){ // TODO: Add your command handler code here m_speed = 200; CMfc_snackeView::GameStart();}void CMfc_snackeView::OnHard(){ // TODO: Add your command handler code here m_speed = 50; CMfc_snackeView::GameStart();}BOOL CMfc_snackeView::OnEraseBkgnd(CDC* pDC){ // TODO: Add your message handler code here and/or call default //即擦除背景由本函数处理,不需要OnPain()来擦除背景 return true; }
- MFC 小游戏之贪吃蛇
- MFC对话框贪吃蛇小游戏
- MFC实现贪吃蛇小游戏
- 控制台小游戏之贪吃蛇
- c++小游戏之贪吃蛇
- C++小游戏之贪吃蛇
- 使用MFC做贪吃蛇小游戏
- MFC之贪吃蛇
- C语言 小游戏之贪吃蛇
- android开发小游戏之贪吃蛇
- 课程设计之贪吃蛇小游戏制造
- 小游戏 贪吃蛇
- 贪吃蛇小游戏
- 贪吃蛇小游戏
- 贪吃蛇小游戏
- Applet贪吃蛇小游戏
- 贪吃蛇小游戏记录:
- 贪吃蛇小游戏笔记
- Red5学习笔记
- CPU和GPU的架构演变
- C和指针 整理
- poj 1562 || zoj 1709 Oil Deposits(DFS)
- 给文件单独指定编译指令
- MFC 小游戏之贪吃蛇
- Android 的 Recovery 模式分析
- JBOSS 5.1 on Ubuntu 10.04
- windows下复制文件夹
- javascript闭包学习总结
- Linux 2.6下的platform_driver和platform_device(结合G870加密磁头驱动分析)
- Dalvik Porting Guide——Dalvik 移植指导
- 利用Windows性能计数器(PerformanceCounter)监控
- CMMB开发过程中遇到的问题