• 贪吃蛇小游戏


    这几天跟别人学习制作了一个小游戏,现在分享一下.

    贪吃蛇,一个经典的小游戏,

    开发环境vs2017

    在WinMain函数中,窗口创建显示完成后添加一句SendMessage(hWnd,WM_SIZE,0,0)来调整窗口的大小,

    //主函数WinMain()

    int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,

             _In_ LPSTR lpCmdLine, _In_ int nShowCmd)

    {

     

             //类名

             TCHAR cls_name[] = TEXT("MyWinClass");

     

             //设计窗口类

             WNDCLASSEX wce = { 0 };

     

             wce.cbSize = sizeof(WNDCLASSEX);

             wce.style = CS_HREDRAW | CS_VREDRAW;

             wce.lpfnWndProc = WindowProc;

             wce.cbClsExtra = 0;

             wce.cbWndExtra = 0;

             wce.hInstance = hInstance;

             wce.hIcon = LoadIcon(hInstance, IDI_APPLICATION);

             wce.hIconSm = wce.hIcon;

             wce.hCursor = LoadCursor(NULL, IDC_ARROW);

             wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);/*::GetStockObject(BLACK_BRUSH)*/ /*黑色刷子*/

             wce.lpszMenuName = NULL;

             wce.lpszClassName = cls_name;

     

             //注册窗口类

             //ATOM nres = RegisterClassEx(&wce);

             if (FALSE == RegisterClassEx(&wce))

                       return 1;

     

             //创建窗口

             HWND hWnd = CreateWindowEx(

                       WS_EX_APPWINDOW,

                       cls_name,

                       TEXT("我的窗口"),

                       WS_OVERLAPPEDWINDOW,

                       200, 120, 600, 400,

                       NULL, NULL, hInstance,

                       NULL);

     

             //回调函数要写上默认的处理DefWindowProc,不然创建失败

             if (!hWnd)

                       return 1;

     

             //显示,更新窗口

             ShowWindow(hWnd, SW_SHOW);

             UpdateWindow(hWnd);

             //调整窗口大小

             SendMessage(hWnd, WM_SIZE, 0, 0);

             //添加加速键表

             HACCEL hAccel = NULL;/*::LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1);*/

     

             //消息循环

             MSG msg;

             while (GetMessage(&msg, NULL, 0, 0))

             {

                       if (!TranslateAccelerator(hWnd, hAccel, &msg))//有加速键表时用这,没有就不用

                       {

                                TranslateMessage(&msg);

                                DispatchMessage(&msg);

                       }

     

             }

     

     

             return 0;

    }

    2.在WM_SIZE消息中

    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

    {

             switch (uMsg)

             {

            

                       case WM_DESTROY:

                                PostQuitMessage(0);

                                break;

     

                       case WM_SIZE:

                       {

                                hdc = GetDC(hWnd);

                                RECT crc, wrc;

                                GetClientRect(hWnd, &crc);

                                GetWindowRect(hWnd, &wrc);

                                int bordrewidth=(wrc.right - wrc.left) - (crc.right - crc.left);

                                int bordreheight = (wrc.bottom - wrc.top) - (crc.bottom - crc.top);

                                SetWindowPos(hWnd, NULL, 0, 0,

                                         600 + bordrewidth, 600 + bordreheight, SWP_NOMOVE);

                                OnStart(hWnd);  //启动游戏

                                ReleaseDC(hWnd, hdc);

                       }break;

        }

        return DefWindowProc(hWnd, uMsg, wParam, lParam);

    }

    这样就固定了窗口大小,不能改变.

    3.在窗口上划分格子(我只分了横竖20)

    定义全局变量

    HDC hdc;

    int row = 20;              //20行

    int col = 20;                //20列

    #define WIDTH        30     //格子的宽度

    #define HEIGHT      30     //格子的高度

    #define MAXSIZE   50     //蛇身最大长度

    POINT m_food;                 //随机食物坐标

    //定义贪吃蛇的结构体

    struct Snake

    {

             POINT m_pos[MAXSIZE];  //身体每个格子的坐标

             int len;   //身体个数

             int m_direction;  //前进方向

    }m_snake;

    在WM_PAINT消息中添加MyPaint()函数画格子

    case WM_PAINT:

                       {

                                PAINTSTRUCT ps;

                                hdc = ::BeginPaint(hWnd, &ps);

                                {

                                         MyPaint(hdc);

                                }

                                EndPaint(hWnd, &ps);

              }break;

    下面就是MyPaint函数的实现

    void MyPaint(HDC hdc)

    {

             HBRUSH hbr = CreateSolidBrush(RGB(255, 0, 0));  //定义红色画刷

             HGDIOBJ hOldBrh = SelectObject(hdc, hbr);

             for (int y=0;y<row;y++)

             {

                       for (int x=0;x<col;x++)

                       {

                                Rectangle(hdc, x*WIDTH, y*HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);  //画格了,行20,列20

                       }

             }

             SelectObject(hdc, hOldBrh);

     

             HBRUSH bhrgreen = CreateSolidBrush(RGB(0, 255, 0));  //绿色画刷

             hOldBrh = SelectObject(hdc, bhrgreen);

             for (int n=0;n<m_snake.len;n++)

             {

                       Rectangle(hdc, m_snake.m_pos[n].x*WIDTH, m_snake.m_pos[n].y*HEIGHT,

                                (m_snake.m_pos[n].x+1)*WIDTH,(m_snake.m_pos[n].y+1)*HEIGHT);  //画蛇的身体

             }

             SelectObject(hdc, hOldBrh);

     

             HBRUSH hbrblue = CreateSolidBrush(RGB(0, 0, 255));  //蓝色画刷

             hOldBrh = SelectObject(hdc, hbrblue);

             Rectangle(hdc, m_food.x*WIDTH, m_food.y*HEIGHT,

                       (m_food.x + 1)*WIDTH, (m_food.y + 1)*HEIGHT);  //画随机食物

         SelectObject(hdc, hOldBrh);

    }

    //随机食物坐标

    void generatefood()

    {

             srand((unsigned)time(NULL));

             m_food.x = rand() % 20;

             m_food.y = rand() % 20;

    }

     

    //初始化蛇

    void init_snake()

    {

             m_snake.len = 3;

             m_snake.m_pos[0].x = 0;

             m_snake.m_pos[0].y = 0;

             m_snake.m_direction = 1;

             for (int n = 1; n < MAXSIZE; n++)

             {

                       m_snake.m_pos[n].x = -1;

                       m_snake.m_pos[n].y = -1;

     

             }

     

             generatefood();

    }

    下面就是启动游戏了

    void OnStart(HWND hWnd)

    {

             init_snake();

             SetTimer(hWnd, 1, 300, NULL); //设置时间

    }

    在WM_TIMER消息中

    case WM_TIMER:

                       {

                //循环输出蛇身位置

                                for (int n = m_snake.len - 1; n >= 1; n--)

                                {

                                         m_snake.m_pos[n] = m_snake.m_pos[n - 1];

                                }

                  //判断前进方向

                                if (0 == m_snake.m_direction)//向上

                                         m_snake.m_pos[0].y = m_snake.m_pos[0].y - 1;

                                if (1 == m_snake.m_direction)//向右

                                         m_snake.m_pos[0].x = m_snake.m_pos[0].x + 1;

                                if (2 == m_snake.m_direction)//向下

                                         m_snake.m_pos[0].y = m_snake.m_pos[0].y + 1;

                                if (3 == m_snake.m_direction)//向左

                                         m_snake.m_pos[0].x = m_snake.m_pos[0].x - 1;

                  //碰到食物蛇身+1,重新随机食物坐标

                                if (m_snake.m_pos[0].x == m_food.x&&m_snake.m_pos[0].y == m_food.y)

                                {

                                         m_snake.len++;

                                         generatefood();

                                }

                  //判断蛇头碰墙,就Game over

                                if (m_snake.m_pos[0].x > 19 || m_snake.m_pos[0].y > 19 || m_snake.m_pos[0].x < 0 || m_snake.m_pos[0].y < 0)

                                {

                                         KillTimer(hWnd, 1);

                                         if (IDYES == MessageBox(hWnd, TEXT("Game over,你想重新开始吗?"),

                                                   TEXT("提示"), MB_YESNO))

                                         {

                                                   OnStart(hWnd);

                                         }

                                         else

                                         {

                                                   PostQuitMessage(0);

                                         }

                                }

                                hdc = GetDC(hWnd);

                                MyPaint(hdc);//重绘窗口所有数据

                                ReleaseDC(hWnd, hdc);

     

                       }break;

    接下来还有方向控制了,这简单

    在WM_KEYDOWN消息中给蛇的m_direction赋值就行了

    case WM_KEYDOWN:

                       {

                                switch (wParam)

                                {

                                case VK_UP:

                                         m_snake.m_direction = 0;

                                         break;

                                case VK_RIGHT:

                                         m_snake.m_direction = 1;

                                         break;

                                case VK_DOWN:

                                         m_snake.m_direction = 2;

                                         break;

                                case VK_LEFT:

                                         m_snake.m_direction = 3;

                                         break;

                                }

                       }break;

    效果:

     

     

    当然还有很多少足处,比如蛇的头可以从身体中穿过.

     

    这些以后再弄了,先学习学习嘛

    签名:GreenLeaf1976
  • 相关阅读:
    Debian/Kali下Subversion的配置
    Linux下解压Windows中的压缩包乱码解决办法
    JavaSocket全双工通信 问题 待解决
    MYSQL学习笔记
    Java Socket 全双工通信
    Kali2017安装后的那些事
    nginx的一次安装与配置
    解决1130 Host 'localhost' is not allowed to connect to this MySQL server
    SimpleDateFormat 和 LocalDate、LocalTime 以及时间大小比较简单示例
    java 线程池 ExeutorService
  • 原文地址:https://www.cnblogs.com/greenleaf1976/p/14744515.html
Copyright © 2020-2023  润新知