(1)匀速运动
#include "stdafx.h" #include "MyGameFrame.h" #include <stdio.h> //全局变量 HWND hWnd; HINSTANCE hInst; HDC hdc, mdc,bufdc; HBITMAP ball,bg; DWORD tPre, tNow; int i; int x,y; RECT rect; // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitWindow(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void MyPaint(HDC hdc); int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 初始化全局字符串 MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitWindow(hInstance, nCmdShow))//初始化窗口 { return FALSE;//如果不成功则返回FALSE,并退出程序 } MSG msg; //创建消息类对象 // TODO: 在此放置运行代码。 //定义局部变量 HBITMAP bmp; char filename[20] = ""; //建立内存DC和窗口DC hdc = GetDC(hWnd); mdc = CreateCompatibleDC(hdc); bufdc = CreateCompatibleDC(hdc); //建立适用位图 bmp = CreateCompatibleBitmap(hdc,640,480); SelectObject(mdc, bmp); //加载图片 ball = (HBITMAP)LoadImage(NULL, "ball.bmp", IMAGE_BITMAP, 52,26, LR_LOADFROMFILE); bg = (HBITMAP)LoadImage(NULL, "bg3.bmp", IMAGE_BITMAP, 640,480, LR_LOADFROMFILE); // 主消息循环: PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//赋初值 while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { tNow = GetTickCount(); if (tNow - tPre >= 30) { GetClientRect(hWnd, &rect);//获取的是以其自身的最左上角的点为坐标原点,此窗口的位置 MyPaint(hdc); } } } return (int)msg.wParam; } // // 函数: MyRegisterClass() // // 注册Windows类,一款游戏有且仅有一个主窗口,与游戏程序唯一对应。创建游戏窗口前要填写窗口类结构体WNDCLASSEX // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex = { wcex.cbSize = sizeof(WNDCLASSEX), CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, WndProc,0,0, hInstance, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)), LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1),NULL, _T("GameFrame"), LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL)) }; return RegisterClassEx(&wcex); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitWindow(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow ( _T("GameFrame"), _T("游戏框架"), WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通样式,不能改变大小,不能最大化 100, 100, 640,480, nullptr, nullptr, hInstance, nullptr ); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) //判断消息 { case WM_CREATE: //执行初始化代码 return(0); break; case WM_KEYDOWN: if (wparam == VK_ESCAPE) PostQuitMessage(0); break; case WM_DESTROY: //关闭程序,发送WM_QUIT消息 PostQuitMessage(0); return(0); break; default: break; } return (DefWindowProc(hwnd, msg, wparam, lparam)); } void MyPaint(HDC hdc) { SelectObject(bufdc, bg); BitBlt(mdc, 0, 0, 640, 480, bufdc, 0, 0, SRCCOPY); SelectObject(bufdc, ball); BitBlt(mdc, x, y, 26, 26, bufdc, 26, 0, SRCAND); BitBlt(mdc, x, y, 26, 26, bufdc, 0, 0, SRCPAINT); BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY); x += 4; //计算X 轴方向贴图坐标 y += 2; //计算Y 轴方向贴图坐标 //如果小球超出边界 if (x >rect.right - 26 || y >rect.bottom - 26) { x = 0; //小球回到窗口的左上角 y = 0; } tPre = GetTickCount(); }
(2)加速运动
#include "stdafx.h" #include "MyGameFrame.h" #include <stdio.h> //全局变量 HWND hWnd; HINSTANCE hInst; HDC hdc, mdc, bufdc; HBITMAP ball, bg; DWORD tPre, tNow; int i; int x, y; RECT rect; int vy, gy; // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitWindow(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void MyPaint(HDC hdc); int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 初始化全局字符串 MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitWindow(hInstance, nCmdShow))//初始化窗口 { return FALSE;//如果不成功则返回FALSE,并退出程序 } MSG msg; //创建消息类对象 // TODO: 在此放置运行代码。 //定义局部变量 HBITMAP bmp; char filename[20] = ""; //建立内存DC和窗口DC hdc = GetDC(hWnd); mdc = CreateCompatibleDC(hdc); bufdc = CreateCompatibleDC(hdc); //建立适用位图 bmp = CreateCompatibleBitmap(hdc, 640, 480); SelectObject(mdc, bmp); //加载图片 ball = (HBITMAP)LoadImage(NULL, "ball.bmp", IMAGE_BITMAP, 52, 26, LR_LOADFROMFILE); bg = (HBITMAP)LoadImage(NULL, "bg3.bmp", IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE); // 主消息循环: PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//赋初值 while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { tNow = GetTickCount(); if (tNow - tPre >= 30) { GetClientRect(hWnd, &rect);//获取的是以其自身的最左上角的点为坐标原点,此窗口的位置 MyPaint(hdc); } } } return (int)msg.wParam; } // // 函数: MyRegisterClass() // // 注册Windows类,一款游戏有且仅有一个主窗口,与游戏程序唯一对应。创建游戏窗口前要填写窗口类结构体WNDCLASSEX // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex = { wcex.cbSize = sizeof(WNDCLASSEX), CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, WndProc,0,0, hInstance, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)), LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1),NULL, _T("GameFrame"), LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL)) }; return RegisterClassEx(&wcex); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitWindow(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow ( _T("GameFrame"), _T("游戏框架"), WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通样式,不能改变大小,不能最大化 100, 100, 640, 480, nullptr, nullptr, hInstance, nullptr ); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) //判断消息 { case WM_CREATE: //执行初始化代码 return(0); break; case WM_KEYDOWN: if (wparam == VK_ESCAPE) PostQuitMessage(0); break; case WM_DESTROY: //关闭程序,发送WM_QUIT消息 PostQuitMessage(0); return(0); break; default: break; } return (DefWindowProc(hwnd, msg, wparam, lparam)); } void MyPaint(HDC hdc) { SelectObject(bufdc, bg); BitBlt(mdc, 0, 0, 640, 480, bufdc, 0, 0, SRCCOPY); SelectObject(bufdc, ball); BitBlt(mdc, x, y, 26, 26, bufdc, 26, 0, SRCAND); BitBlt(mdc, x, y, 26, 26, bufdc, 0, 0, SRCPAINT); BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY); x += 2; //计算X 轴方向贴图坐标 vy = 0; gy = 10; vy = vy + gy; //计算Y 轴方向速度分量 y += vy - 1 / 2 * gy; //计算Y 轴方向贴图坐标 //如果小球超出边界 if (y > rect.bottom - 26) { //小球接触到窗口下边框的判断 y = rect.bottom - 26; vy = -vy - gy; //弥补位置变化动能的损失 //竖直方向加速度为-1的曲线运动 } if (x>rect.right - 26) x = 0; tPre = GetTickCount(); }
(3)碰撞现象
#include "stdafx.h" #include "MyGameFrame.h" #include <stdio.h> #include <math.h> //全局变量 HWND hWnd; HINSTANCE hInst; HDC hdc, mdc; HBITMAP bmpball; int i; double x, y; double xlast, ylast; double vx=9; double vy=5; RECT rect; // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitWindow(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void collide(int startX, int startY, int endX, int endY); int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 初始化全局字符串 MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitWindow(hInstance, nCmdShow))//初始化窗口 { return FALSE;//如果不成功则返回FALSE,并退出程序 } MSG msg; //创建消息类对象 // TODO: 在此放置运行代码。 //获取窗口 //GetClientRect用于取得指定窗口的客户区域大小 //每个窗口区域可分为两部分,用于显示内容的区域叫Client区(客户区),NonClient(非客户区)用于显示命令按钮及窗口标题等。 //非客户区的绘图是由WM_NCPAINT发出的。 GetClientRect(hWnd, &rect); //建立内存DC和窗口DC hdc = GetDC(hWnd); mdc = CreateCompatibleDC(hdc); //加载图片 bmpball = (HBITMAP)LoadImage(NULL, "ball.bmp", IMAGE_BITMAP, 52, 26, LR_LOADFROMFILE); //创建定时器 SetTimer(hWnd, 1, 60, NULL); // 主消息循环: PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//赋初值 while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int)msg.wParam; } // // 函数: MyRegisterClass() // // 注册Windows类,一款游戏有且仅有一个主窗口,与游戏程序唯一对应。创建游戏窗口前要填写窗口类结构体WNDCLASSEX // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex = { wcex.cbSize = sizeof(WNDCLASSEX), CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, WndProc,0,0, hInstance, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)), LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1),NULL, _T("GameFrame"), LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL)) }; return RegisterClassEx(&wcex); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitWindow(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow ( _T("GameFrame"), _T("游戏框架"), WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通样式,不能改变大小,不能最大化 100, 100, 640, 480, nullptr, nullptr, hInstance, nullptr ); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) //判断消息 { case WM_CREATE: //执行初始化代码 return(0); break; case WM_TIMER: { SelectObject(mdc, bmpball); BitBlt(hdc, int(xlast), int(ylast), 26, 26, mdc, 26, 0, WHITENESS); BitBlt(hdc, int(xlast), int(ylast), 26, 26, mdc, 0, 0, WHITENESS); BitBlt(hdc, int(x), int(y), 26, 26, mdc, 26, 0, SRCAND); BitBlt(hdc, int(x), int(y), 26, 26, mdc, 0, 0, SRCPAINT); xlast = x; //上次贴图X坐标 ylast = y; //上次贴图Y坐标 x += vx; y += vy; if (y < 0) { //是否碰到上边缘 vy = -vy; y = 0; } if (x < 0) { //是否碰到左边缘 vx = -vx; x = 0; } collide(rect.right, 20, 400, rect.bottom); //右边斜面 collide(400, rect.bottom, 0, 200); MoveToEx(hdc, rect.right, 20, NULL); //画线 LineTo(hdc, 400, rect.bottom); LineTo(hdc, 0, 200); } break; case WM_DESTROY: DeleteDC(mdc); ReleaseDC(hWnd, hdc); DeleteObject(bmpball); KillTimer(hWnd, 1); //关闭程序,发送WM_QUIT消息 PostQuitMessage(0); return(0); break; default: break; } return (DefWindowProc(hwnd, msg, wparam, lparam)); } void collide(int startX, int startY, int endX, int endY) { float va, vb; //碰撞后速度, int计算误差导致小球出去 float lx, ly, fx, fy, m, n; int ox, oy; //小球球心位置 lx = (float)endX - startX; //X轴向量 ly = (float)endY - startY; //Y轴向量 fx = (float)startY - endY; //X轴法向量 fy = (float)endX - startX; //Y轴法向量 ////圆心X 坐标 //ox = x + 13; //球心X坐标变为小球边缘X坐标 ox = x + 13 - 13 * fx / sqrt(pow(fx, 2) + pow(fy, 2)); ////圆心Y 坐标 //oy = y + 13; //球心Y坐标变为小球边缘Y坐标 oy = y + 13 - 13 * fy / sqrt(pow(fx, 2) + pow(fy, 2)); m = (vx*(startY - oy) + vy * (ox - startX)) / (lx*vy - ly * vx); n = (lx*(oy - startY) + ly * (startX - ox)) / (vx*ly - vy * lx); if (m >= 0 && m <= 1 && n >= 0 && n <= 1) //碰撞反应 { x += vx * n; //修正小球位置 y += vy * n; va = -2 * (fx*vx + fy * vy)*fx / (pow(fx, 2) + pow(fy, 2)) + vx; vb = -2 * (fx*vx + fy * vy)*fy / (pow(fx, 2) + pow(fy, 2)) + vy; vx = va; //修正小球速度 vy = vb; } }
(4)粒子瀑布
#include "stdafx.h" #include "MyGameFrame.h" #include <stdio.h> #include <math.h> #include <time.h> //粒子数组大小 #define dm 1000 //粒子结构体 typedef struct { float cx, cy; float vx, vy; float vyacc; float life; float decay; } PARTICLE; //全局变量 HWND hWnd; HINSTANCE hInst; HDC hdc, mdc; HBITMAP bmp; PARTICLE Drop[dm]; DWORD tPre, tNow; // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitWindow(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void InitializeDrop(int x, int y); void MoveDrop(void); void MyPaint(HDC hdc); int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 初始化全局字符串 MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitWindow(hInstance, nCmdShow))//初始化窗口 { return FALSE;//如果不成功则返回FALSE,并退出程序 } MSG msg; //创建消息类对象 // TODO: 在此放置运行代码。 srand((unsigned)time(NULL)); //建立内存DC和窗口DC hdc = GetDC(hWnd); mdc = CreateCompatibleDC(hdc); //建立适用位图 bmp = CreateCompatibleBitmap(hdc, 640, 480); SelectObject(mdc, bmp); InitializeDrop(30, 30); MyPaint(hdc); // 主消息循环: //初始化msg PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { tNow = GetTickCount(); if (tNow - tPre >= 10) MyPaint(hdc); } } return (int)msg.wParam; } // // 函数: MyRegisterClass() // // 注册Windows类,一款游戏有且仅有一个主窗口,与游戏程序唯一对应。创建游戏窗口前要填写窗口类结构体WNDCLASSEX // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex = { wcex.cbSize = sizeof(WNDCLASSEX), CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, WndProc,0,0, hInstance, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)), LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1),NULL, _T("GameFrame"), LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL)) }; return RegisterClassEx(&wcex); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitWindow(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow ( _T("GameFrame"), _T("游戏框架"), WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通样式,不能改变大小,不能最大化 100, 100, 640, 480, nullptr, nullptr, hInstance, nullptr ); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) //判断消息 { case WM_CREATE: //执行初始化代码 return(0); break; case WM_DESTROY: //关闭程序,发送WM_QUIT消息 PostQuitMessage(0); return(0); break; default: break; } return (DefWindowProc(hwnd, msg, wparam, lparam)); } void InitializeDrop(int x, int y) { int i; for (i = 0; i<dm; i++) { if (Drop[i].life <= 0) { Drop[i].cx = (float)x; Drop[i].cy = (float)y; Drop[i].vx = (float)(0.0007*(rand() % 500 + 500)); Drop[i].vy = (float)(0.1*(rand() % 10)); Drop[i].vyacc = 0.05f; Drop[i].life = 1.0f; Drop[i].decay = (float)(0.0005*(rand() % 250)); } } } void MoveDrop(void) { for (int i = 0; i<dm; i++) { if (Drop[i].life>0) { Drop[i].cx += Drop[i].vx; Drop[i].cy += Drop[i].vy; Drop[i].vy += Drop[i].vyacc; Drop[i].life -= Drop[i].decay; if (Drop[i].cx >= 500) Drop[i].vx *= (-1); if ((Drop[i].cy <= 10) || (Drop[i].cy >= 350)) { Drop[i].vy *= (-1); Drop[i].decay += 0.05f; Drop[i].vy += 0.1f; } } } } void MyPaint(HDC hdc) { HDC dc = CreateCompatibleDC(hdc); BitBlt(mdc, 0, 0, 640, 480, dc, 0, 0, BLACKNESS); //清理mdc MoveDrop(); InitializeDrop(30, 30); for (int i = 0; i<dm; i++) SetPixel(mdc, (int)Drop[i].cx, (int)Drop[i].cy,RGB(128, 255, 255)); BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY); tPre = GetTickCount(); }