Windows粒子系统

  1 #include <windows.h>
  2 #include <tchar.h>    //swprintf_s函数所需的头文件
  3 #include  <time.h>
  4 
  5 #pragma comment(lib, "winmm.lib")    //playSound
  6 #pragma comment(lib, "Msimg32.lib")    //TransparentBlt
  7 
  8 #define WINDOW_WIDTH    950
  9 #define WINDOW_HEIGHT    710
 10 #define WINDOW_TITLE    L"Windows粒子系统"
 11 // 表示粒子数量
 12 #define FLYSTAR_NUMBER    100    
 13 // 表示粒子持续帧数,修改每次星光绽放持续的时间   
 14 #define FLYSTAR_LASTED_FRAME 60                    
 15 
 16 
 17 struct FLYSTAR
 18 {
 19     int x;       //星光所在的x坐标
 20     int y;       //星光所在的y坐标
 21     int vx;      //星光x方向的速度
 22     int vy;      //星光y方向的速度
 23     int lasted;  //星光存在的时间
 24     BOOL exist;  //星光是否存在
 25 };
 26 // 环境,内存句柄
 27 HDC    g_hdc = NULL, g_mdc = NULL, g_bufdc = NULL;
 28 HBITMAP g_hStar = NULL, g_hBackGround = NULL;
 29 DWORD g_tPre = 0, g_tNow = 0;
 30 // 储存内部窗口区域的坐标
 31 RECT g_rect;
 32 FLYSTAR FlyStars[FLYSTAR_NUMBER]; 
 33 int g_StarNum = 0; 
 34 
 35 // 回调函数,窗口过程函数
 36 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
 37 BOOL Game_Init(HWND hwnd);
 38 VOID Game_Paint(HWND hwnd);
 39 BOOL Game_CleanUp(HWND hwnd);
 40 
 41 
 42 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
 43 {
 44     WNDCLASSEX wndClass = { 0 };
 45     wndClass.cbSize = sizeof(WNDCLASSEX);
 46     wndClass.style = CS_HREDRAW | CS_VREDRAW;
 47     wndClass.lpfnWndProc = WndProc;
 48     wndClass.cbClsExtra = 0;
 49     wndClass.cbWndExtra = 0;
 50     wndClass.hInstance = hInstance;
 51     wndClass.hIcon = 0;
 52     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
 53     // 白色画刷句柄
 54     wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 55     // 用一个以空终止的字符串,指定菜单资源的名字
 56     wndClass.lpszMenuName = NULL;
 57     //窗口类的名字
 58     wndClass.lpszClassName = L"Game Develop";
 59 
 60     if (!RegisterClassEx(&wndClass))
 61         return -1;
 62 
 63     // 正式创建窗口
 64     HWND hwnd = CreateWindow(L"Game Develop", WINDOW_TITLE,
 65         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
 66         WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
 67 
 68     MoveWindow(hwnd, 150, 50, WINDOW_WIDTH, WINDOW_HEIGHT, true);
 69     ShowWindow(hwnd, nShowCmd);
 70     UpdateWindow(hwnd);
 71 
 72     if (!Game_Init(hwnd))
 73     {
 74         MessageBox(hwnd, L"资源初始化失败", L"消息窗口", 0);
 75         return FALSE;
 76     }
 77 
 78     PlaySound(L"music.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
 79 
 80     MSG msg = { 0 };
 81     while (msg.message != WM_QUIT)
 82     {
 83         // 查看应用程序消息队列,有消息时将队列中的消息派发出去
 84         if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
 85         {
 86             TranslateMessage(&msg);
 87             DispatchMessage(&msg);
 88         }
 89         else
 90         {
 91             g_tNow = GetTickCount();
 92             // 重绘
 93             if (g_tNow - g_tPre >= 40)
 94                 Game_Paint(hwnd);
 95         }
 96     }
 97 
 98     // 程序准备结束,注销窗口类
 99     UnregisterClass(L"Game Develop", wndClass.hInstance);
100     return 0;
101 }
102 
103 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
104 {
105     switch (message)
106     {
107     case WM_KEYDOWN:
108         if (wParam == VK_ESCAPE)
109             PostQuitMessage(0);
110         break;
111         
112     case WM_DESTROY:
113         Game_CleanUp(hwnd);
114         PostQuitMessage(0);
115         break;
116 
117         //调用缺省的窗口过程
118     default:
119         return DefWindowProc(hwnd, message, wParam, lParam);
120     }
121     return 0;
122 }
123 
124 BOOL Game_Init(HWND hwnd)
125 {
126     // 用系统时间初始化 
127     // 随机数发生器的初始化函数
128     srand((unsigned)time(NULL));
129 
130     HBITMAP bmp;
131     g_hdc = GetDC(hwnd);
132     g_mdc = CreateCompatibleDC(g_hdc);
133     g_bufdc = CreateCompatibleDC(g_hdc);
134     bmp = CreateCompatibleBitmap(g_hdc, WINDOW_WIDTH, WINDOW_HEIGHT);
135     
136     SelectObject(g_mdc, bmp);
137     g_hBackGround = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE);
138     g_hStar = (HBITMAP)LoadImage(NULL, L"star.bmp", IMAGE_BITMAP, 30, 30, LR_LOADFROMFILE);
139 
140     // 取得内部窗口大小
141     GetClientRect(hwnd, &g_rect);
142 
143     Game_Paint(hwnd);
144     return TRUE;
145 }
146 
147 VOID Game_Paint(HWND hwnd)
148 {
149     // 先在mdc中贴上背景图
150     SelectObject(g_bufdc, g_hBackGround);
151     // 将源矩形区域直接拷贝到目标矩形区域
152     BitBlt(g_mdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_bufdc, 0, 0, SRCCOPY);
153 
154     // 创建粒子
155     if (g_StarNum == 0)
156     {
157         // 随机设置爆炸点
158         int x = rand() % g_rect.right;
159         int y = rand() % g_rect.bottom;
160 
161         for (int i = 0; i < FLYSTAR_NUMBER; i++)
162         {
163             FlyStars[i].x = x;
164             FlyStars[i].y = y;
165             FlyStars[i].lasted = 0;
166             // x,y方向的移动速度随机为1—15之间的一个值
167             if (i % 4 == 0)
168             {
169                 FlyStars[i].vx = -(1 + rand() % 15);
170                 FlyStars[i].vy = -(1 + rand() % 15);
171             }
172             if (i % 4 == 1)
173             {
174                 FlyStars[i].vx = (1 + rand() % 15);
175                 FlyStars[i].vy = (1 + rand() % 15);
176             }
177             if (i % 4 == 2)
178             {
179                 FlyStars[i].vx = -(1 + rand() % 15);
180                 FlyStars[i].vy = (1 + rand() % 15);
181             }
182             if (i % 4 == 3)
183             {
184                 FlyStars[i].vx = (1 + rand() % 15);
185                 FlyStars[i].vy = -(1 + rand() % 15);
186             }
187             FlyStars[i].exist = true;
188         }
189         g_StarNum = FLYSTAR_NUMBER;
190     }
191 
192     // 显示粒子
193     for (int i = 0; i < FLYSTAR_NUMBER; i++)
194     {
195         if (FlyStars[i].exist)
196         {
197             SelectObject(g_bufdc, g_hStar);
198             TransparentBlt(g_mdc, FlyStars[i].x, FlyStars[i].y, 30, 30, g_bufdc, 0, 0, 30, 30, RGB(0, 0, 0));
199 
200             // 下一次坐标
201             FlyStars[i].x += FlyStars[i].vx;
202             FlyStars[i].y += FlyStars[i].vy;
203             // 在每进行一次贴图后,将粒子的存在时间累加1.
204             FlyStars[i].lasted++;
205             // 进行条件判断,若某粒子跑出窗口区域一定的范围,则将该粒子设为不存在,且粒子数随之递减
206             if (FlyStars[i].x <= -10 || FlyStars[i].x>g_rect.right || FlyStars[i].y <= -10 || FlyStars[i].y>g_rect.bottom || FlyStars[i].lasted>FLYSTAR_LASTED_FRAME)
207             {
208                 FlyStars[i].exist = false;  //删除星光粒子 
209                 g_StarNum--;                    //递减星光总数
210             }
211         }
212     }
213     BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY);
214     g_tPre = GetTickCount();
215 }
216 
217 BOOL Game_CleanUp(HWND hwnd)
218 {
219     // 释放资源对象
220     DeleteObject(g_hBackGround);
221     DeleteObject(g_hStar);
222     DeleteDC(g_bufdc);
223     DeleteDC(g_mdc);
224     ReleaseDC(hwnd, g_hdc);
225     return TRUE;
226 }

 

posted @ 2015-04-21 21:45  ht-beyond  阅读(607)  评论(0编辑  收藏  举报