zoukankan      html  css  js  c++  java
  • C项目实践--贪吃蛇(2)

    12.按键处理

    函数名称:key_down

    函数功能:按键处理函数,主要包括:1.刚开始或结束时的按键处理,游戏开始时,按任意键进入游戏,游戏运行过程中按回车键是游戏的暂停或开始的切换键;2.游戏运行过程中,按上、下、左、右键对蛇移动的方向进行控制。具体实现如下:

    void key_down(WPARAM wParam)
    {
        if(state != game_run)
        {
            if(wParam == VK_RETURN)
            {
                //在游戏不是运行状态时按下回车键
                //则运行游戏
                switch(state)
                {
                case game_start:
                        state = game_run;
                        break;
                case game_pause:
                    state = game_run;
                    //state = game_pause;
                    break;
                case game_over:
                    new_game();
                    state = game_run;
                    break;
                }
            }
        }
        else{
            //否则在游戏运行状态下
            switch(wParam)
            {
            case VK_UP: //向上键
                //dirt表示蛇当前的移动方向,属于全局变量
                if(dirt != DOWN)
                {
                    dirt = UP;
                }
                break;
            case VK_LEFT: //左键
                if(dirt != RIGHT)
                {
                    dirt = LEFT;
                }
                break;
            case VK_RIGHT:
                if(dirt != LEFT)
                {
                    dirt = RIGHT;
                }
                break;
            case VK_DOWN:
                if(dirt != UP)
                {
                    dirt = DOWN;
                }
                break;
            case VK_RETURN:
                state = game_pause;
                break;
            }
        }
        //刷新绘图窗口
        InvalidateRect(gameWND , NULL , TRUE);
    }

    13.改变窗口大小

    函数名称:resize

    函数功能:改变窗口大小时将调用本函数,根据窗口现有的大小,改变内存位图和字体等的大小,以便窗口绘图时适应新的窗口尺寸。具体实现如下:

    void resize()
    {
        HDC hdc ;
        LOGFONT lf; //字体逻辑结构
     
        //根据窗口的大小改变内存位图的大小
        hdc = GetDC(gameWND);
        GetClientRect(gameWND,&clientRC);
        SelectObject(memDC,memBMOld);
        DeleteObject(memBM);
        memBM = CreateCompatibleBitmap(hdc,clientRC.right,clientRC.bottom);
        memBMOld = (HBITMAP)SelectObject(memDC,memBM);
     
        //根据窗口的大小改变大字体的大小
        DeleteObject(bigFont);
        memset(&lf,0,sizeof(LOGFONT));
        lf.lfWidth = (clientRC.right - clientRC.left) / CHARS_IN_LINE;
        lf.lfHeight = (clientRC.bottom - clientRC.top) / 4;
        lf.lfItalic = 1;
        lf.lfWeight = FW_BOLD;
        bigFont = CreateFontIndirect(&lf);
        //根据窗口的大小改变小字体的大小
        DeleteObject(smallFont);
        lf.lfHeight = clientRC.bottom / (ROWS + 2);
        lf.lfWidth = lf.lfHeight*3 / 4;
        lf.lfItalic = 0;
        lf.lfWeight = FW_NORMAL;
        smallFont = CreateFontIndirect(&lf);
     
        ReleaseDC(gameWND,hdc);
    }

    14.初始化

    函数名称:initialize

    函数功能:初始化游戏。具体实现如下:

    void initialize()
    {
        PAINTSTRUCT ps;
        LOGFONT lf;
        HDC hdc;
        int i;
     
        hdc = GetDC(gameWND);
        GetClientRect(gameWND,&clientRC); //取得客户区绘图窗口的大小
        memDC = CreateCompatibleDC(hdc); //创建内存DC
        memBM = CreateCompatibleBitmap(hdc,clientRC.right,clientRC.bottom);//创建内存位图
        memBMOld = (HBITMAP)SelectObject(memDC,memBM);
        blackBrush = CreateSolidBrush(BLACK);//创建画笔和字体等
        snakeBrush = CreateSolidBrush(GREEN);
        for(i = 0; i < FOOD_COUNT; i++)
        {
            foodBrush[i] = CreateSolidBrush(food_color[i]);
        }
        grayPen  = CreatePen(PS_SOLID , 1, GRAY);
        memset(&lf, 0, sizeof(LOGFONT));
        //设置字体属性
        lf.lfWidth = (clientRC.right- clientRC.left) / CHARS_IN_LINE;
        lf.lfHeight = (clientRC.bottom - clientRC.top) / 4;
        lf.lfItalic = 1;
        lf.lfWeight = FW_BOLD;
        bigFont = CreateFontIndirect(&lf);
        lf.lfHeight = clientRC.bottom / (ROWS + 2);
        lf.lfWeight = lf.lfHeight*3/4;
        lf.lfItalic = 0;
        lf.lfWeight = FW_NORMAL;
        smallFont = CreateFontIndirect(&lf);
        ReleaseDC(gameWND,hdc);
        EndPaint(gameWND,&ps);
    }

    15.释放资源

    函数名称:finalize

    函数功能:游戏结束之前,释放初始化游戏时创建的资源。具体实现如下:

    void finalize()
    {
        int i = 0;
        DeleteObject(blackBrush);
        DeleteObject(snakeBrush);
        for(i = 0; i < FOOD_COUNT; i++)
        {
            DeleteObject(foodBrush[i]);
        }
     
        DeleteObject(grayPen);
        DeleteObject(bigFont);
        DeleteObject(smallFont);
        SelectObject(memDC,memBMOld);
        DeleteObject(memBM);
        DeleteDC(memDC);
    }

    16.回调函数

    函数名称:WndProc

    函数功能:用来处理windows消息。具体实现如下:

    //响应Windows消息的回调函数,用来处理windows消息
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
        case WM_SIZE: //改变窗口大小
            resize();
            return 0;
        case WM_ERASEBKGND:
            return 0;
        case WM_PAINT:  //绘制内存位图到窗口
            paint();
            return 0;
        case WM_KEYDOWN:
            key_down(wParam); //用户操作处理
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    17.程序入口

    函数名称:WinMain

    函数功能:Windows程序的入口,类似于DOS程序的main函数,所以这个函数名必须是WinMain。具体实现如下:

    int WINAPI WinMain(HINSTANCE  hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        MSG msg;
        WNDCLASS wndclass; //窗口类
     
        //窗口类属性
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
        wndclass.lpszMenuName  = NULL;
        wndclass.lpszClassName = APP_NAME;
        RegisterClass(&wndclass); //注册窗口类
        //创建窗口
        gameWND = CreateWindow(APP_NAME,
            APP_TITLE,
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,NULL,
            hInstance, NULL);
        //初始化游戏资源
        initialize();
        //显示窗口
        ShowWindow(gameWND, iCmdShow);
        UpdateWindow(gameWND);//更新窗口
        new_game();//新游戏
        for(;;)//进入windows消息循环, 直到接收到退出消息为止
        {
            if(state == game_run)
            {
                run_game();
            }
            if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
            {
                if(GetMessage(&msg,NULL,0,0))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }else{
                    break;
                }
            }
        }
        finalize(); //释放资源
        return msg.wParam;//返回消息参数
     
    }
    自此整个项目功能基本实现完毕

    5.系统操作过程

    游戏运行后,首先进入欢迎主界面,如图:

    image

    在欢迎主界面中按任意键进入贪吃蛇游戏,游戏界面如图:

    image

    游戏结束界面如图:

    image

    6.总结与Bug记录

    Bug.1

    系统提示Char* 与LPCWSTR 不兼容,就是就在每个char*变量前加上(LPCWSTR)强制转换,就没有提示错误信息了,但是运行之后,发现字符串显示为乱码。 上网查资料其中有一方案说,通过右键项目属性将Unicode字符串更改为多字节字符串即可。按照执行,乱码解决。

    总结

    下一步待实现功能:

    1.随着贪吃蛇吃的食物的增多,应该适当加快其运动速度以增加游戏难度

    2.游戏桌面的大小应适应不同分辨率屏幕自动按相应大小显示,使得全屏时,游戏桌面及提示信息全部在同一屏幕上显示。

  • 相关阅读:
    开开心心
    HOW HE/SHE'S SEEN
    天池
    sql server deadlock跟踪的四种方法
    reduce 好东西
    object方法
    页面横向滚动 联动 进度条
    浅拷贝、深拷贝
    图片下载
    axios简单封装
  • 原文地址:https://www.cnblogs.com/AI-Algorithms/p/3427580.html
Copyright © 2011-2022 走看看