Сделать проверку на столкновение шаров между собой - C (СИ)
Формулировка задачи:
Всем привет!
подскажите пожалуйста как сделать проверку на соударение шаров между собой, точнее как определить угол между шарами после удара. Вот кусок кода. Зарание спасибо.
void ballsImpact( struct myBall *ballArray, const int ballsSize) { int firstB=0; int secondB=0; double tmp=0; double rast=0; double ap1p1=0; double Vx1; double Vy1; double Vx2; double Vy2; double pi=3.14; double bet=0; double x1=0; double x2=0; double y1=0; double y2=0; for (firstB=0; firstB<(ballsSize-1); firstB++) { for (secondB=firstB+1; secondB<ballsSize; secondB++) { double X =ballArray[firstB].X - ballArray[secondB].X; double Y =ballArray[firstB].Y - ballArray[secondB].Y; double OcAngle = Pi/2-atan(X/Y); double i=0; double D= ballArray[firstB].R+ballArray[secondB].R; rast=pow(pow(X,2.0)+pow(Y,2.0),0.5); if (rast<D+0.01) { Vx1=ballArray[firstB].V*cos(ballArray[firstB].alpha); Vy1=ballArray[firstB].V*sin(ballArray[firstB].alpha); Vx2=ballArray[secondB].V*cos(ballArray[secondB].alpha); Vy2=ballArray[secondB].V*sin(ballArray[secondB].alpha); bet=atan2(Y,X); x1=Vx1*cos(-bet)-Vy1*sin(-bet); //поворачиваем на угол -бета y1=Vx1*sin(-bet)+Vy1*cos(-bet); //чтобы линия проведеная через x2=Vx2*cos(-bet)-Vy2*sin(-bet); //центры шаров совпала с осью y2=Vx2*sin(-bet)+Vy2*cos(-bet); // Х экранной системы координат Vx1=x2*cos(bet)-y1*sin(bet); //теперь поворачиваем обратно Vy1=x2*sin(bet)+y1*cos(bet); //только проеции скорости на ось Х Vx2=x1*cos(bet)-y2*sin(bet); // у двух шаров меняем местами Vy2=x1*sin(bet)+y2*cos(bet); //(по закону сохранения импульса) ballArray[firstB].V=pow(pow(Vx1,2)+pow(Vy1,2),0.5); ballArray[secondB].V=pow(pow(Vx2,2)+pow(Vy2,2),0.5); } } } }
Решение задачи: «Сделать проверку на столкновение шаров между собой»
textual
Листинг программы
#include <windows.h> #include <gl/gl.h> #include <Math.h> LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); void EnableOpenGL(HWND hwnd, HDC*, HGLRC*); void DisableOpenGL(HWND, HDC, HGLRC); void MyWork(); const double Pi=3.14; const double step=0.009; const double eps=0.0001; double Dist=0; struct myWin { }; struct myBall { //X,Y,Vx,Vy,R,M; double X; double Y; double Vx; double Vy; double R; double M; double V; double A; double alpha; }; void drawBall( const struct myBall *ball); void setBall( struct myBall *ball, double X, double Y,double V,double M,double Alph); void proverka( struct myBall *ball); void ballsImpact(struct myBall *ballArray, const int ballsSize); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wcex; HWND hwnd; HDC hDC; HGLRC hRC; MSG msg; BOOL bQuit = FALSE; float theta = 0.0f; /* register window class */ wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_OWNDC; wcex.lpfnWndProc = WindowProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wcex.lpszMenuName = NULL; wcex.lpszClassName = "GLSample"; wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);; if (!RegisterClassEx(&wcex)) return 0; /* create main window */ hwnd = CreateWindowEx(0, "GLSample", "OpenGL Sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, nCmdShow); /* enable OpenGL for the window */ EnableOpenGL(hwnd, &hDC, &hRC); /** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * initiation of my variables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ const int BallSize=2; struct myWin okno_1; struct myBall BallS[BallSize]; /** X,Y,V,M,ALP*/ setBall( &BallS[0], -1.0, -1.0, 6.0, 2.0, Pi/4.5); setBall( &BallS[1], 1.0, 1.0, 6.0, 2.0, Pi/4); double FrameBorder=0.9; double k=0.9; int frameDelay=51; /* program main loop */ while (!bQuit) { /* check for messages */ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { /* handle or dispatch messages */ if (msg.message == WM_QUIT) { bQuit = TRUE; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } else { /* OpenGL animation code goes here */ glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0f, 1.0f, 1.0f); glColor3f(0.0f, 0.0f, 0.0f); glPushMatrix(); /** PROVERKA */ int k; for (k=0; k<BallSize; k++) { proverka( &BallS[k]); //walls } ballsImpact( &BallS[0],BallSize); for (k=0; k<BallSize; k++) { drawBall( &BallS[k]); } /** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ glPopMatrix(); SwapBuffers(hDC); theta += 1.0f; Sleep (frameDelay); } } /* shutdown OpenGL */ DisableOpenGL(hwnd, hDC, hRC); /* destroy the window explicitly */ DestroyWindow(hwnd); return msg.wParam; } void setBall( struct myBall *ball, double X, double Y,double V,double M,double Alph) { double Mu=0.05; ball->X=X; ball->Y=Y; ball->V=V; ball->M=M; ball->R=0.1; ball->A= (Mu/ball->R)*9.8; ball->alpha=Alph; } void drawBall( const struct myBall *ball) { const int dots=40; const double pi=3.14; const double angle=(2*pi)/dots; int i; glBegin(GL_LINES); for (i=0; i<dots; i++) { double x = ball->X + ball->R *cos(i*angle); double y = ball->Y + ball->R *sin(i*angle); glVertex2f(x, y); } glEnd(); } void ballsImpact( struct myBall *ballArray, const int ballsSize) { int firstB=0; int secondB=0; double tmp=0; double rast=0; double ap1p1=0; double Vx1; double Vy1; double Vx2; double Vy2; double pi=3.14; double bet=0; double x1=0; double x2=0; double y1=0; double y2=0; for (firstB=0; firstB<(ballsSize-1); firstB++) { for (secondB=firstB+1; secondB<ballsSize; secondB++) { double X =ballArray[firstB].X - ballArray[secondB].X; double Y =ballArray[firstB].Y - ballArray[secondB].Y; double OcAngle = Pi/2-atan(X/Y); double i=0; double D= ballArray[firstB].R+ballArray[secondB].R; rast=pow(pow(X,2.0)+pow(Y,2.0),0.5); if (rast<D+0.01) { //pricel=sqrt(pow(ballArray[firstB].Y-ballArray[secondB].Y,2.0)+pow(ballArray[firstB].X-ballArray[secondB].X,2.0)); //printf("Collision %f\n",rast); Vx1=ballArray[firstB].V*cos(ballArray[firstB].alpha); Vy1=ballArray[firstB].V*sin(ballArray[firstB].alpha); Vx2=ballArray[secondB].V*cos(ballArray[secondB].alpha); Vy2=ballArray[secondB].V*sin(ballArray[secondB].alpha); bet=atan2(Y,X); x1=Vx1*cos(-bet)-Vy1*sin(-bet); //поворачиваем на угол -бета y1=Vx1*sin(-bet)+Vy1*cos(-bet); //чтобы линия проведеная через x2=Vx2*cos(-bet)-Vy2*sin(-bet); //центры шаров совпала с осью y2=Vx2*sin(-bet)+Vy2*cos(-bet); // Х экранной системы координат Vx1=x2*cos(bet)-y1*sin(bet); //теперь поворачиваем обратно Vy1=x2*sin(bet)+y1*cos(bet); //только проеции скорости на ось Х Vx2=x1*cos(bet)-y2*sin(bet); // у двух шаров меняем местами Vy2=x1*sin(bet)+y2*cos(bet); //(по закону сохранения импульса) ballArray[firstB].V=pow(pow(Vx1,2)+pow(Vy1,2),0.5); ballArray[secondB].V=pow(pow(Vx2,2)+pow(Vy2,2),0.5); } } } } void proverka( struct myBall *ball ) { if (ball->alpha<0) { ball->alpha+=2*Pi; } //change V ball->V = ball->V - ball->A * step; if (ball->V<eps) { ball->V=0; } if (ball->V!=0) { /**peremeshenie*/ double Way=ball->V*step; ball->X= ball->X +Way * cos(ball->alpha); ball->Y= ball->Y +Way * sin(ball->alpha); } int borders=0; // 1000 --left // 0100 --bottom // 0010 --right // 0001 --up // right border if (ball->X>=(1.0-ball->R)) { borders+=10; ball->X=(1.0-ball->R); } // left border if (ball->X<=(-1.0+ball->R)) { borders+=1000; ball->X=(-1.0+ball->R); } if (ball->Y>=(1.0-ball->R)) { borders+=1; ball->Y=(1.0-ball->R); } // left border if (ball->Y<=(-1.0+ball->R)) { borders+=100; ball->Y=(-1.0+ball->R); } int muktiplier=1; switch (borders) { case 1000://left muktiplier=+2; if (ball->alpha==Pi) { muktiplier=-2; } else if ((ball->alpha>Pi/2)&&((ball->alpha<Pi))) { muktiplier=-1; } else { muktiplier=+1; } break; case 1001://left + up muktiplier=+2; break; case 1100://left + bottom muktiplier=-2; break; case 10:// 0010 right if (ball->alpha==0.0) { muktiplier=+2; } else if ((ball->alpha<Pi/2)&&((ball->alpha>0))) { muktiplier=+1; } else { muktiplier=-1; } break; case 11:// 0011right +UP muktiplier=+2; break; case 110:// 0110right+bottom muktiplier=-2; break; case 1://0001 up muktiplier=+2; break; case 100://0100 bottom muktiplier=-2; break; } if (borders!=0) { ball->alpha=(muktiplier*Pi)-ball->alpha; } } LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CLOSE: PostQuitMessage(0); break; case WM_DESTROY: return 0; case WM_KEYDOWN: { switch (wParam) { case VK_ESCAPE: PostQuitMessage(0); break; } } break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC) { PIXELFORMATDESCRIPTOR pfd; int iFormat; /* get the device context (DC) */ *hDC = GetDC(hwnd); /* set the pixel format for the DC */ ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cDepthBits = 16; pfd.iLayerType = PFD_MAIN_PLANE; iFormat = ChoosePixelFormat(*hDC, &pfd); SetPixelFormat(*hDC, iFormat, &pfd); /* create and enable the render context (RC) */ *hRC = wglCreateContext(*hDC); wglMakeCurrent(*hDC, *hRC); } void DisableOpenGL (HWND hwnd, HDC hDC, HGLRC hRC) { wglMakeCurrent(NULL, NULL); wglDeleteContext(hRC); ReleaseDC(hwnd, hDC); }