3.俄罗斯方块项目

  • 游戏界面设计

宏定义如下:

1 #define ELEM 30
2 #define X_SIZE 510
3 #define Y_SIZE 660
  • 设置窗口大小和位置
     1 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
     2 {
     3    HWND hWnd;
     4 
     5    hInst = hInstance; // 将实例句柄存储在全局变量中
     6 
     7    //改变窗口大小和位置,并且把最大框功能去掉
     8    hWnd = CreateWindow(szWindowClass, L"池国维--俄罗斯方块",WS_SYSMENU | WS_MINIMIZEBOX,
     9        500, 200, X_SIZE + 18, Y_SIZE + 18 , NULL, NULL, hInstance, NULL);
    10 
    11    if (!hWnd)
    12    {
    13       return FALSE;
    14    }
    15 
    16    ShowWindow(hWnd, nCmdShow);
    17    UpdateWindow(hWnd);
    18 
    19    return TRUE;
    20 }

     

    此时的截图:

  • 设置游戏背景
    • 使用双缓冲绘图
1 HDC g_hdc;//全局DC
2 HDC g_hdcBuf;//缓存DC
3 HDC g_hdcBg;//背景DC
4 HBITMAP g_hBmp;//背景

创建四个函数,一个用于载入资源,一个用于初始化,一个用于画图,一个用于回收资源

1 VOID Load_Game(HWND);
2 void Init_Game();
3 VOID Paint_Game();
4 VOID Clear_Game();

Load_Game()函数

 1 VOID Load_Game(HWND hWnd)
 2 {
 3     //获取窗口的DC
 4     g_hdc = GetDC(hWnd);
 5 
 6     //以下实现g_hdcBuf的初始化
 7     //创建与窗口兼容的缓存DC
 8     g_hdcBuf = CreateCompatibleDC(g_hdc);
 9     //创建位图资源
10     g_hBmp = CreateCompatibleBitmap(g_hdc, X_SIZE, Y_SIZE);
11     //位图和缓存DC绑定
12     SelectObject(g_hdcBuf, g_hBmp);
13 
14     //以下实现g_hdcBg的初始化
15     //载入位图资源
16     HBITMAP hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BG));
17     //创建与窗口兼容的背景DC
18     g_hdcBg = CreateCompatibleDC(g_hdc);
19     //把位图和背景DC绑定
20     SelectObject(g_hdcBg, hBmp);
21     //删除位图资源
22     DeleteObject(hBmp);
23     return;
24 }

在Init_Game()中画格子中画边框,以及画背景

 1 VOID Init_Game()
 2 {
 3     
 4     //初始化方块
 5     srand(GetTickCount());
 6     int x = rand() % CNT;
 7     //随机初始化当前方块
 8     memcpy(g_astCur, g_astTetris[x], sizeof(g_astCur));
 9 
10     //随机初始化下一个方块
11     x = rand()&CNT;
12     memcpy(g_astNext, g_astTetris[x], sizeof(g_astNext));
13 
14     //方块出现的初始位置
15     g_x = (10 - 4) / 2;
16     g_y = 1;
17 
18 }

 

Paint_Game()函数

 1 VOID Paint_Game()
 2 {
 3     //g_hdcBg存放在g_hdcBuf中 加载背景到缓存DC
 4     BitBlt(g_hdcBuf, 0, 0, X_SIZE, Y_SIZE, g_hdcBg, 0, 0, SRCCOPY);
 5     //画一些边框
 6     int x, y;
 7     HBRUSH hBrush = CreateSolidBrush(RGB(0xbb, 0xff, 0xff));
 8     for (x = 0; x < X_SIZE / ELEM; x++)
 9     {
10         for (y = 0; y < Y_SIZE / ELEM; y++)
11         {
12             if (x == 0 || x == X_SIZE / ELEM - 1 || y == 0 || y == Y_SIZE / ELEM - 1 || x == 11)
13             {
14                 SelectObject(g_hdcBuf, hBrush);
15                 Rectangle(g_hdcBuf, x * ELEM, y*ELEM, (x + 1)*ELEM, (y + 1)*ELEM);
16             }
17         }
18     }
19     //删除画刷
20     DeleteObject(SelectObject(g_hdcBuf, GetStockObject(NULL_BRUSH)));
21 
22     //显示当前下降的方块
23     for (int x = 0; x < 4; x++)
24     {
25         for (int y = 0; y < 4; y++)
26         {
27             if (g_astCur[x][y])
28             {
29                 SelectObject(g_hdcBuf, (HBRUSH)(GetStockObject(WHITE_BRUSH)));
30                 Rectangle(g_hdcBuf, (g_x + x) * 30, (g_y + y) * 30, (g_x + x + 1) * 30, (g_y + y + 1) * 30);
31 
32                 SelectObject(g_hdcBuf, (HBRUSH)(GetStockObject(GRAY_BRUSH)));
33                 Rectangle(g_hdcBuf, (g_x + x) * 30 + 5, (g_y + y) * 30 + 5, (g_x + x + 1) * 30 - 5, (g_y + y + 1) * 30 - 5);
34             }
35         }
36     }
37 
38     //显示下一个方块
39     for (int y = 0; y < 4; y++)
40     {
41         for (int x = 0; x < 4; x++)
42         {
43             if (g_astNext[y][x])
44             {
45                 SelectObject(g_hdcBuf, (HBRUSH)(GetStockObject(WHITE_BRUSH)));
46                 Rectangle(g_hdcBuf, (12 + x) * 30 + 20, (2 + y) * 30 , (12 + x + 1) * 30 +20, (2 + y + 1) * 30);
47 
48                 SelectObject(g_hdcBuf, (HBRUSH)(GetStockObject(GRAY_BRUSH)));
49                 Rectangle(g_hdcBuf, (12 + x) * 30 + 20 + 5, (2 + y) * 30 + 5, (12 + x + 1) * 30 + 20 -5, (2 + y + 1) * 30 - 5);
50             }
51         }
52     }
53 
54     //g_hdcBuf存放在g_hdc中 把缓存DC内的东西刷新到游戏DC
55     BitBlt(g_hdc,0,0,X_SIZE,Y_SIZE,g_hdcBuf,0,0,SRCCOPY);
56 }

 

Clear_Game()函数

1 VOID Clear_Game()
2 {
3     DeleteObject(g_hBmp);
4     DeleteDC(g_hdcBuf);
5     DeleteDC(g_hdcBg);
6 
7     return;
8 }

 

由于背景只需要画一次,所以Load_Game(),Init_Game()在InitInstance函数中调用

 1 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
 2 {
 3    HWND hWnd;
 4 
 5    hInst = hInstance; // 将实例句柄存储在全局变量中
 6 
 7    //改变窗口大小和位置,并且把最大框功能去掉
 8    hWnd = CreateWindow(szWindowClass, L"池国维--俄罗斯方块", WS_SYSMENU | WS_MINIMIZEBOX,
 9        500, 200, X_SIZE + 18, Y_SIZE + 40 , NULL, NULL, hInstance, NULL);
10 
11    if (!hWnd)
12    {
13       return FALSE;
14    }
15    Load_Game(hWnd);
16    Init_Game();
17 
18    ShowWindow(hWnd, nCmdShow);
19    UpdateWindow(hWnd);
20 
21    return TRUE;
22 }

此时截图:

 

 俄罗斯方块用4*4的格子表示:

用数组表示

 1 INT g_astTetris[][4][4] =
 2 {
 3     { { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
 4     { { 1, 1, 1, 0 }, { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0, } },
 5     { { 1, 1, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
 6     { { 1, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
 7     { { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
 8     { { 0, 1, 1, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
 9     { { 1, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
10 };
11 INT g_astCur[4][4];//当前是那一块方块
12 INT g_astNext[4][4];//下一块是哪一块方块

在Init_Game中初始化方块:

 1 #define CNT sizeof(g_astTetris)/sizeof(g_astTetris[0])
 2 VOID Init_Game()
 3 {
 4     //g_hdcBg存放在g_hdcBuf中 加载背景到缓存DC
 5     BitBlt(g_hdcBuf, 0, 0, X_SIZE, Y_SIZE, g_hdcBg, 0, 0, SRCCOPY);
 6     //画一些边框
 7     int x, y;
 8     HBRUSH hBrush = CreateSolidBrush(RGB(0xbb, 0xff, 0xff));
 9     for (x = 0; x < X_SIZE / ELEM; x++)
10     {
11         for (y = 0; y < Y_SIZE / ELEM; y++)
12         {
13             if (x == 0 || x == X_SIZE / ELEM - 1 || y == 0 || y == Y_SIZE / ELEM - 1 || x == 11)
14             {
15                 SelectObject(g_hdcBuf, hBrush);
16                 Rectangle(g_hdcBuf, x * ELEM, y*ELEM, (x + 1)*ELEM, (y + 1)*ELEM);
17             }
18         }
19     }
20     //删除画刷
21     DeleteObject(SelectObject(g_hdcBuf, GetStockObject(NULL_BRUSH)));
22 
23     //初始化方块
24     srand(GetTickCount());
25     int x = rand() % CNT;
26     //随机初始化当前方块
27     memcpy(g_astCur, g_astTetris[x], sizeof(g_astCur));
28 }

设定方块的初始位置:

1 INT g_x, g_y;//当前方块下降到那个位置

并在Init_Game中初始化

1 //方块出现的初始位置
2     g_x = (10 - 4) / 2;
3     g_y = 1;

在Paint_Game中画方块:

 1 VOID Paint_Game()
 2 {
 3     
 4     //显示当前下降的方块
 5     for (int x = 0; x < 4; x++)
 6     {
 7         for (int y = 0; y < 4; y++)
 8         {
 9             if (g_astCur[x][y])
10             {
11                 SelectObject(g_hdcBuf, (HBRUSH)(GetStockObject(WHITE_BRUSH)));
12                 Rectangle(g_hdcBuf, (g_x + x) * 30, (g_y + y) * 30, (g_x + x + 1) * 30, (g_y + y + 1) * 30);
13 
14                 SelectObject(g_hdcBuf, (HBRUSH)(GetStockObject(GRAY_BRUSH)));
15                 Rectangle(g_hdcBuf, (g_x + x) * 30 + 5, (g_y + y) * 30 + 5, (g_x + x + 1) * 30 - 5, (g_y + y + 1) * 30 - 5);
16             }
17         }
18     }
19 
20     //显示下一个方块
21     for (int y = 0; y < 4; y++)
22     {
23         for (int x = 0; x < 4; x++)
24         {
25             if (g_astNext[y][x])
26             {
27                 SelectObject(g_hdcBuf, (HBRUSH)(GetStockObject(WHITE_BRUSH)));
28                 Rectangle(g_hdcBuf, (12 + x) * 30 + 20, (2 + y) * 30 , (12 + x + 1) * 30 +20, (2 + y + 1) * 30);
29 
30                 SelectObject(g_hdcBuf, (HBRUSH)(GetStockObject(GRAY_BRUSH)));
31                 Rectangle(g_hdcBuf, (12 + x) * 30 + 20 + 5, (2 + y) * 30 + 5, (12 + x + 1) * 30 + 20 -5, (2 + y + 1) * 30 - 5);
32             }
33         }
34     }
35 
36     //g_hdcBuf存放在g_hdc中 把缓存DC内的东西刷新到游戏DC
37     BitBlt(g_hdc,0,0,X_SIZE,Y_SIZE,g_hdcBuf,0,0,SRCCOPY);
38 }

 此时项目截图:

设置定时器动起来:

在消息循环中加入以下代码:

 1 case WM_CREATE:
 2         SetTimer(hWnd, 1, 200, 0);
 3         break;
 4     case WM_TIMER:
 5         //下降
 6         if (CheckMeet(g_x,g_y+1))//可以下降
 7         {
 8             g_y++;
 9         }
10         else//停止下降
11         {
12             RefreshMap();
13             //生成新的方块
14             memcpy(g_astCur, g_astNext, sizeof(g_astCur));
15             g_x = 4;
16             g_y = 1;
17             srand(GetTickCount());
18             int x = rand() % CNT;
19             memcpy(g_astNext, g_astTetris[x], sizeof(g_astNext));
20         }
21         Paint_Game();
22         break;
23     case WM_COMMAND:
24         wmId    = LOWORD(wParam);
25         wmEvent = HIWORD(wParam);
26         // 分析菜单选择: 
27         switch (wmId)
28         {
29         case IDM_ABOUT:
30             DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
31             break;
32         case IDM_EXIT:
33             DestroyWindow(hWnd);
34             break;
35         default:
36             return DefWindowProc(hWnd, message, wParam, lParam);
37         }
38         break;
39     case WM_PAINT:
40         hdc = BeginPaint(hWnd, &ps);
41         // TODO:  在此添加任意绘图代码...
42         Paint_Game();
43         EndPaint(hWnd, &ps);
44         break;
45 
46     case WM_KEYDOWN:
47         if (g_gameOver)//游戏结束
48         {
49             break;
50         }
51         switch (wParam)
52         {
53         case VK_LEFT:
54             if (CheckMeet(g_x - 1, g_y))
55             {
56                 g_x--;
57             }
58             break;
59         case VK_RIGHT:
60             if (CheckMeet(g_x + 1, g_y))
61             {
62                 g_x++;
63             }
64             break;
65         case VK_UP://变形
66             break;
67         case VK_DOWN://移到下面
68             break;
69         }
70         Paint_Game();
71         break;

 

CheckMeet函数:

//无碰撞返回TRUE,否则返回FALSE
BOOL CheckMeet()
{
    //判断是否到了最下面
    for (int y = 0; y < 4; y++)
    {
        for (int x = 0; x < 4; x++)
        {
            if (g_astCur[y][x])
            {
                if (g_y + x>=20) 
                    return FALSE;
            }
        }
    }
    return TRUE;
}

 

转载于:https://www.cnblogs.com/xiaochi/p/8283116.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值