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

posted @ 2013-11-17 10:44  AI Algorithms  阅读(911)  评论(3编辑  收藏  举报