⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demo13_8.cpp

📁 windows游戏编程大师源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
DDraw_Shutdown();

// now directsound
DSound_Stop_All_Sounds();
DSound_Shutdown();

// shut down directinput
DInput_Shutdown();

// return success
return(1);

} // end Game_Shutdown

//////////////////////////////////////////////////////////

void Ball_Sound(void)
{        
// this functions hunts for an open handle to play a collision sound

// start a hit sound
for (int sound_index=0; sound_index < 8; sound_index++)
    {
    // test if this sound is playing
    if (DSound_Status_Sound(ball_ids[sound_index])==0)
       {
       DSound_Play(ball_ids[sound_index]);
       break;
       } // end if

     } // end for 

} // end Ball_Sound

///////////////////////////////////////////////////////////

void Collision_Response(void)
{
// this function does all the "real" physics to determine if there has
// been a collision between any ball and any other ball, if there is a collision
// the function uses the mass of each ball along with the intial velocities to 
// compute the resulting velocities

// from the book we know that in general 
// va2 = (e+1)*mb*vb1+va1(ma - e*mb)/(ma+mb)
// vb2 = (e+1)*ma*va1+vb1(ma - e*mb)/(ma+mb)

// and the objects will have direction vectors co-linear to the normal
// of the point of collision, but since we are using spheres here as the objects
// we know that the normal to the point of collision is just the vector from the 
// center's of each object, thus the resulting velocity vector of each ball will
// be along this normal vector direction

// step 1: test each object against each other object and test for a collision
// there are better ways to do this other than a double nested loop, but since
// there are a small number of objects this is fine, also we want to somewhat model
// if two or more balls hit simulataneously

for (int ball_a = 0; ball_a < NUM_BALLS; ball_a++)
     {
     for (int ball_b = ball_a+1; ball_b < NUM_BALLS; ball_b++)
         {
         if (ball_a == ball_b) 
            continue;

         // compute the normal vector from a->b
         float nabx = (balls[ball_b].varsF[INDEX_X] - balls[ball_a].varsF[INDEX_X] );
         float naby = (balls[ball_b].varsF[INDEX_Y] - balls[ball_a].varsF[INDEX_Y] );
         float length = sqrt(nabx*nabx + naby*naby);

         // is there a collision?
         if (length <= 2.0*(BALL_RADIUS*.75))
            {
            // the balls have made contact, compute response

            // compute the response coordinate system axes
            // normalize normal vector
            nabx/=length;
            naby/=length;

            // compute the tangential vector perpendicular to normal, simply rotate vector 90
            float tabx =  -naby;
            float taby =  nabx;

            // draw collision
            DDraw_Lock_Primary_Surface();

            // blue is normal
            Draw_Clip_Line(balls[ball_a].varsF[INDEX_X]+0.5, 
               balls[ball_a].varsF[INDEX_Y]+0.5,
               balls[ball_a].varsF[INDEX_X]+20*nabx+0.5,
               balls[ball_a].varsF[INDEX_Y]+20*naby+0.5,
               252, primary_buffer, primary_lpitch); 

            // yellow is tangential
            Draw_Clip_Line(balls[ball_a].varsF[INDEX_X]+0.5, 
               balls[ball_a].varsF[INDEX_Y]+0.5,
               balls[ball_a].varsF[INDEX_X]+20*tabx+0.5,
               balls[ball_a].varsF[INDEX_Y]+20*taby+0.5,
               251, primary_buffer, primary_lpitch); 

             DDraw_Unlock_Primary_Surface();

            // tangential is also normalized since it's just a rotated normal vector
        
            // step 2: compute all the initial velocities
            // notation ball: (a,b) initial: i, final: f, n: normal direction, t: tangential direction

            float vait = DOT_PRODUCT(balls[ball_a].varsF[INDEX_XV], 
                                     balls[ball_a].varsF[INDEX_YV], 
                                     tabx, taby);

            float vain = DOT_PRODUCT(balls[ball_a].varsF[INDEX_XV], 
                                     balls[ball_a].varsF[INDEX_YV], 
                                     nabx, naby);

            float vbit = DOT_PRODUCT(balls[ball_b].varsF[INDEX_XV], 
                                     balls[ball_b].varsF[INDEX_YV], 
                                     tabx, taby);

            float vbin = DOT_PRODUCT(balls[ball_b].varsF[INDEX_XV], 
                                     balls[ball_b].varsF[INDEX_YV], 
                                     nabx, naby);


            // now we have all the initial velocities in terms of the n and t axes
            // step 3: compute final velocities after collision, from book we have
            // note: all this code can be optimized, but I want you to see what's happening :)

            float ma = balls[ball_a].varsF[INDEX_MASS];
            float mb = balls[ball_b].varsF[INDEX_MASS];
 
            float vafn = (mb*vbin*(cof_E+1) + vain*(ma - cof_E*mb)) / (ma + mb);
            float vbfn = (ma*vain*(cof_E+1) - vbin*(ma - cof_E*mb)) / (ma + mb);

            // now luckily the tangential components are the same before and after, so
            float vaft = vait;
            float vbft = vbit;

            // and that's that baby!
            // the velocity vectors are:
            // object a (vafn, vaft)
            // object b (vbfn, vbft)    
 
            // the only problem is that we are in the wrong coordinate system! we need to 
            // translate back to the original x,y coordinate system, basically we need to 
            // compute the sum of the x components relative to the n,t axes and the sum of
            // the y components relative to the n,t axis, since n,t may both have x,y
            // components in the original x,y coordinate system
            
            float xfa = vafn*nabx + vaft*tabx;
            float yfa = vafn*naby + vaft*taby;

            float xfb = vbfn*nabx + vbft*tabx;
            float yfb = vbfn*naby + vbft*taby;

            // store results
            balls[ball_a].varsF[INDEX_XV] = xfa;
            balls[ball_a].varsF[INDEX_YV] = yfa;

            balls[ball_b].varsF[INDEX_XV] = xfb;
            balls[ball_b].varsF[INDEX_YV] = yfb;

            // update position
            balls[ball_a].varsF[INDEX_X]+=balls[ball_a].varsF[INDEX_XV];
            balls[ball_a].varsF[INDEX_Y]+=balls[ball_a].varsF[INDEX_YV];

            balls[ball_b].varsF[INDEX_X]+=balls[ball_b].varsF[INDEX_XV];
            balls[ball_b].varsF[INDEX_Y]+=balls[ball_b].varsF[INDEX_YV];

            } // end if

         } // end for ball2

     } // end for ball1

} // end Collision_Response

//////////////////////////////////////////////////////////

int Game_Main(void *parms)
{
// this is the workhorse of your game it will be called
// continuously in real-time this is like main() in C
// all the calls for you game go here!

int index; // looping var

// start the timing clock
Start_Clock();

// clear the drawing surface
//DDraw_Fill_Surface(lpddsback, 0);

// lock back buffer and copy background into it
DDraw_Lock_Back_Surface();

// draw background
Draw_Bitmap(&background_bmp, back_buffer, back_lpitch,0);

// draw table
HLine(TABLE_MIN_X, TABLE_MAX_X, TABLE_MIN_Y, 250, back_buffer, back_lpitch);
HLine(TABLE_MIN_X, TABLE_MAX_X, TABLE_MAX_Y, 250, back_buffer, back_lpitch);
VLine(TABLE_MIN_Y, TABLE_MAX_Y, TABLE_MIN_X, 250, back_buffer, back_lpitch);
VLine(TABLE_MIN_Y, TABLE_MAX_Y, TABLE_MAX_X, 250, back_buffer, back_lpitch);


// unlock back surface
DDraw_Unlock_Back_Surface();

// read keyboard
DInput_Read_Keyboard();


// check for change of e
if (keyboard_state[DIK_RIGHT])
    cof_E+=.01;
else
if (keyboard_state[DIK_LEFT])
    cof_E-=.01;

float total_ke_x = 0, total_ke_y = 0;

// move all the balls and compute system momentum
for (index=0; index < NUM_BALLS; index++)
    {
    // move the ball
    balls[index].varsF[INDEX_X]+=balls[index].varsF[INDEX_XV];
    balls[index].varsF[INDEX_Y]+=balls[index].varsF[INDEX_YV];

    // add x,y contributions to kinetic energy
    total_ke_x+=(balls[index].varsF[INDEX_XV]*balls[index].varsF[INDEX_XV]*balls[index].varsF[INDEX_MASS]);
    total_ke_y+=(balls[index].varsF[INDEX_YV]*balls[index].varsF[INDEX_YV]*balls[index].varsF[INDEX_MASS]);

    } // end fof
    
// test for boundary collision with virtual table edge, no need for collision
// response here, I know what's going to happen :)
for (index=0; index < NUM_BALLS; index++)
    {
    if ((balls[index].varsF[INDEX_X] >= TABLE_MAX_X-BALL_RADIUS) || 
        (balls[index].varsF[INDEX_X] <= TABLE_MIN_X+BALL_RADIUS))
        {
        // invert velocity
        balls[index].varsF[INDEX_XV] = -balls[index].varsF[INDEX_XV];

        balls[index].varsF[INDEX_X]+=balls[index].varsF[INDEX_XV];
        balls[index].varsF[INDEX_Y]+=balls[index].varsF[INDEX_YV];

        // start a hit sound
        Ball_Sound();

        } // end if

    if ((balls[index].varsF[INDEX_Y] >= TABLE_MAX_Y-BALL_RADIUS) || 
        (balls[index].varsF[INDEX_Y] <= TABLE_MIN_Y+BALL_RADIUS))
        {
        // invert velocity
        balls[index].varsF[INDEX_YV] =-balls[index].varsF[INDEX_YV];

        balls[index].varsF[INDEX_X]+=balls[index].varsF[INDEX_XV];
        balls[index].varsF[INDEX_Y]+=balls[index].varsF[INDEX_YV];

        // play sound
        Ball_Sound();

        } // end if

    } // end for index

// draw the balls
for (index=0; index < NUM_BALLS; index++)
    {
    balls[index].x = balls[index].varsF[INDEX_X]+0.5-BALL_RADIUS;
    balls[index].y = balls[index].varsF[INDEX_Y]+0.5-BALL_RADIUS;
    
    Draw_BOB(&balls[index], lpddsback);
    } // end for

// draw the velocity vectors
DDraw_Lock_Back_Surface();
for (index=0; index < NUM_BALLS; index++)
    {
    Draw_Clip_Line(balls[index].varsF[INDEX_X]+0.5, 
              balls[index].varsF[INDEX_Y]+0.5,
              balls[index].varsF[INDEX_X]+2*balls[index].varsF[INDEX_XV]+0.5,
              balls[index].varsF[INDEX_Y]+2*balls[index].varsF[INDEX_YV]+0.5,
              246, back_buffer, back_lpitch); 
    } // end for
DDraw_Unlock_Back_Surface();

// draw the title
Draw_Text_GDI("ELASTIC Object-Object Collision Response DEMO, Press <ESC> to Exit.",10, 10,RGB(255,255,255), lpddsback);

// draw the title
sprintf(buffer,"Coefficient of Restitution e=%f, use <RIGHT>, <LEFT> arrow to change.", cof_E);
Draw_Text_GDI(buffer,10, 30,RGB(255,255,255), lpddsback);

sprintf(buffer,"Total System Kinetic Energy Sum(1/2MiVi^2)=%f ",0.5*sqrt(total_ke_x*total_ke_x+total_ke_y*total_ke_y));
Draw_Text_GDI(buffer,10, 465, RGB(255,255,255), lpddsback);


// flip the surfaces
DDraw_Flip();

// run collision response algorithm here
Collision_Response();

// sync to 30 fps = 1/30sec = 33 ms
Wait_Clock(33);

// check of user is trying to exit
if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
    {
    PostMessage(main_window_handle, WM_DESTROY,0,0);

    // stop all sounds
    DSound_Stop_All_Sounds();

    // do a screen transition
    // Screen_Transitions(SCREEN_GREENNESS,NULL,0);
    } // end if

// return success
return(1);

} // end Game_Main

//////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -