Сделать проверку на столкновение шаров между собой - 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);
}

Оцени полезность:

7   голосов , оценка 3.571 из 5
Похожие ответы