思路:
先算出每个小球下一个位置的x和y,并根据先后碰撞顺序决定每个小球最后的x和y值,同时还得考虑碰撞到边界反弹的问题。
一开始搞错了判断先后顺序的方法,浪费了贼多时间(逃
代码:
#include <windows.h>
#include <tchar.h>
#include <cmath>
#include <time.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //窗口函数说明
//入口函数代码
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
HWND hWnd;
MSG msg;
char szWindowClass[] = "窗口示例"; //窗口类名
char szTitle[] = "My Windows"; //窗口标题名
//初始化窗口类
wcex.cbSize = sizeof(WNDCLASSEX); //窗口类的大小
wcex.style = 0; //窗口类型为默认类型
wcex.lpfnWndProc = WndProc; //窗口处理函数为WndProc
wcex.cbClsExtra = 0; //窗口类无扩展
wcex.cbWndExtra = 0; //窗口实例无扩展
wcex.hInstance = hInstance; //当前实例句柄
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION); //窗口的图标为默认图标
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //窗口采用箭头光标
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //窗口背景颜色
wcex.lpszMenuName = NULL; //窗口中无菜单
wcex.lpszClassName = szWindowClass; //窗口类名为 szWindowClass
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION); //窗口的小图标为默认图标
//窗口类的注册
if(!RegisterClassEx(&wcex))
{
MessageBox(NULL, ("窗口类注册失败!"), ("窗口注册"), NULL);
return 1;
}
//创建窗口
hWnd = CreateWindow(
szWindowClass, //窗口类名
szTitle, //窗口实例的标题名
WS_OVERLAPPEDWINDOW, //窗口的风格
CW_USEDEFAULT, CW_USEDEFAULT, //窗口左上角坐标为默认值
CW_USEDEFAULT, CW_USEDEFAULT, //窗口的高和宽为默认值
NULL, //此窗口无父窗口
NULL, //此窗口无主菜单
hInstance, //创建此窗口应用程序的当前句柄
NULL //不使用该值
);
if(!hWnd) //如果创建窗口失败则发出警告
{
MessageBox(NULL, "创建窗口失败!", ("创建窗口"), NULL);
return 1;
}
ShowWindow(hWnd, nCmdShow); //显示窗口
UpdateWindow(hWnd); //绘制用户区
while(GetMessage(&msg, NULL, 0, 0)) //消息循环
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam; //程序终止时将信息返回系统
}
//窗口函数代码
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
HPEN hpen;
HBRUSH hbrush;
PAINTSTRUCT ps;
RECT rect;
POINT pt;
GetClientRect(hWnd, &rect);
int i,j;
static double x[10];
static double y[10];
static double vx[10], vy[10];
static int r[10];
static int uddis[10] = {1,1,1,1,1,1,1,1,1,1};
static int lrdis[10] = {1,1,1,1,1,1,1,1,1,1};
static double nextx[10];
static double nexty[10];
double xx[10];
double yy[10];
for(i = 0; i < 10; i++)
{
xx[i] = -1;
yy[i] = -1;
vx[i] = i > 3 ? i : i + 2;
vy[i] = i > 3 ? i : i + 2;
}
for(i = 0; i < 10; i++)
{
r[i] = rect.right / 50 + rect.right / 500 * i;
}
x[0] = 0;
y[0] = 0;
for(i = 1; i < 10; i++)
{
x[i] = rect.right / 20 * i;
y[i] = rect.bottom / 20 * i;
}
static int flag2 = 0;
switch(message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
hbrush = CreateSolidBrush(RGB(255,0,0));
if(flag2 > 0)
{
for(i = 0; i < 10; i++)
{
x[i] = nextx[i];
y[i] = nexty[i];
}
}
for(i = 0; i < 5; i++)
{
hbrush = CreateSolidBrush(RGB(255, 0, i * 50));
SelectObject(hdc, hbrush);
Ellipse(hdc, x[i] - r[i], y[i] - r[i], x[i] + r[i], y[i] + r[i]);
DeleteObject(hbrush);
}
for(i = 5; i < 10; i++)
{
hbrush = CreateSolidBrush(RGB(0, 255, i * 50));
SelectObject(hdc, hbrush);
Ellipse(hdc, x[i] - r[i], y[i] - r[i], x[i] + r[i], y[i] + r[i]);
DeleteObject(hbrush);
}
for(i = 0; i < 10; i++)
{
nextx[i] = x[i] + lrdis[i] * vx[i];
nexty[i] = y[i] + uddis[i] * vy[i];
}
for(i = 0; i < 10; i++)
{
double minx = rect.left + r[i];
double miny = rect.top + r[i];
double maxx = rect.right - r[i];
double maxy = rect.bottom - r[i];
for(j = 0; j < 10; j++)
{
if(i == j)
continue;
int sum = pow(nextx[i] - nextx[j], 2) + pow(nexty[i] - nexty[j], 2);
double sum2 = sqrt(sum);
if(sum2 < r[i] + r[j] && nextx[i] > nextx[j])
{
if(nextx[j] - (nextx[j] - nextx[i]) * (r[i] + r[j]) / sum2 > minx)
minx = (double)(nextx[j] - (nextx[j] - nextx[i]) * (r[i] + r[j]) / sum2);
if(nexty[i] > nexty[j])
{
if(nexty[j] - (nexty[j] - nexty[i]) * (r[i] + r[j]) / sum2 < maxy)
{
maxy = (double)nexty[j] - (nexty[j] - nexty[i]) * (r[i] + r[j]) / sum2;
}
}
if(nexty[i] < nexty[j])
{
if(nexty[j] - (nexty[j] - nexty[i]) * (r[i] + r[j]) / sum2 > miny)
{
miny = (double)nexty[j] - (nexty[j] - nexty[i]) * (r[i] + r[j]) / sum2;
}
}
}
if(sum2 < r[i] + r[j] && nextx[i] < nextx[j])
{
if(nextx[j] - (nextx[j] - nextx[i]) * (r[i] + r[j]) / sum2 < maxx)
maxx = (double)nextx[j] - (nextx[j] - nextx[i]) * (r[i] + r[j]) / sum2;
if(nexty[i] > nexty[j])
{
if(nexty[j] - (nexty[j] - nexty[i]) * (r[i] + r[j]) / sum2 < maxy)
{
maxy = (double)nexty[j] - (nexty[j] - nexty[i]) * (r[i] + r[j]) / sum2;
}
}
if(nexty[i] < nexty[j])
{
if(nexty[j] - (nexty[j] - nexty[i]) * (r[i] + r[j]) / sum2 > miny)
{
miny = (double)nexty[j] - (nexty[j] - nexty[i]) * (r[i] + r[j]) / sum2;
}
}
}
}
if(minx != rect.left + r[i])
{
xx[i] = minx;
lrdis[i] = -lrdis[i];
}
else if(nextx[i] < rect.left + r[i])
{
xx[i] = rect.left + r[i];
lrdis[i] = -lrdis[i];
}
if(maxx != rect.right - r[i])
{
xx[i] = maxx;
lrdis[i] = -lrdis[i];
}
else if(nextx[i] > rect.right - r[i])
{
xx[i] = rect.right - r[i];
lrdis[i] = -lrdis[i];
}
if(miny != rect.top + r[i])
{
yy[i] = miny;
uddis[i] = -uddis[i];
}
else if(nexty[i] < rect.top + r[i])
{
yy[i] = rect.top + r[i];
uddis[i] = -uddis[i];
}
if(maxy != rect.bottom - r[i])
{
yy[i] = maxy;
uddis[i] = -uddis[i];
}
else if(nexty[i] > rect.bottom - r[i])
{
yy[i] = rect.bottom - r[i];
uddis[i] = -uddis[i];
}
}
for(i = 0; i < 10; i++)
{
if(xx[i] != -1)
nextx[i] = xx[i];
if(yy[i] != -1)
nexty[i] = yy[i];
}
flag2 = 1;
DeleteObject(hbrush);
EndPaint(hWnd, &ps);
Sleep(10);
InvalidateRect(hWnd, NULL, 1);
break;
case WM_SIZE:
InvalidateRect(hWnd, NULL, true);
break;
case WM_DESTROY:
PostQuitMessage(0); //调用POSTQuitMessage发出WM_QUIT消息
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam); //默认时采用系统消息默认处理函数
break;
}
return 0;
}
运行效果图: