示例#1
0
void    Clear_Random_Field()            /* Clear a random field to RB_EMPTY. There's a
                                           great chance, that we get an empty field, so
                                           we retry 50 times */
{
int     i,x,y;

for(i=0;i<50;i++)                       /* Retry 50 times */
    {
    x=(rand()%(RB_X-2))+1;              /* Random position on playing ground */
    y=(rand()%(RB_Y-2))+1;
    if(RB_Array[x][y]!=RB_EMPTY)        /* Clear the symbol, but only if the field isn't empty */
        {
        RB_Array[x][y]=RB_EMPTY;
        Draw_Bitmap(RB_EMPTY,ROP_SRCCOPY,(x-1)*RB_SIZE,(y-1)*RB_SIZE);
        break;
        }
    }
}
示例#2
0
void    Put_Random_Field(void)          /* Put a random symbol in a random field */
{
int     i,k,x,y;

do
   {
    x=(rand()%(RB_X-2))+1;              /* Random position on playing ground */
    y=(rand()%(RB_Y-2))+1;
    i=(rand()%136);                     /* Fill symbols with probability classes */
    if((i>=0) && (i<17)) k=RB_VP;
    if((i>=17) && (i<35)) k=RB_MP;
    if((i>=35) && (i<60)) k=RB_GP;
    if((i>=60) && (i<105)) k=RB_BP;
    if((i>=105) && (i<115)) k=RB_LX;
    if((i>=115) && (i<125)) k=RB_RX;
    if((i>=125) && (i<136)) k=RB_HOLE;
    if(RB_Array[x][y]==RB_EMPTY)        /* Add the symbol, but only if the field is empty */
        {
        RB_Array[x][y]=k;
        Draw_Bitmap(k,ROP_SRCCOPY,(x-1)*RB_SIZE,(y-1)*RB_SIZE);
        break;
        }
    }while(1);                          /* Loop until one symbol added in a random field */
}
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
int          dx,dy;             // general deltas used in collision detection
 
static int   player_moving = 0; // tracks player motion
static PALETTEENTRY glow = {0,0,0,PC_NOCOLLAPSE};  // used to animation red border
static int glow_count = 0, glow_dx = 5;

// start the timing clock
Start_Clock();

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

// lock the back buffer
DDraw_Lock_Back_Surface();

// draw the background reactor image
Draw_Bitmap(&reactor, back_buffer, back_lpitch, 0);

// unlock the back buffer
DDraw_Unlock_Back_Surface();

// read keyboard and other devices here
DInput_Read_Keyboard();

// reset motion flag
player_moving = 0;

// test direction of motion, this is a good example of testing the keyboard
// although the code could be optimized this is more educational

if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_UP]) 
   {
   // move skelaton
   skelaton.x+=2;
   skelaton.y-=2;
   dx=2; dy=-2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_NEAST)
      Set_Animation_BOB(&skelaton,SKELATON_NEAST);

   } // end if
else
if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_UP]) 
   {
   // move skelaton
   skelaton.x-=2;
   skelaton.y-=2;
   dx=-2; dy=-2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_NWEST)
      Set_Animation_BOB(&skelaton,SKELATON_NWEST);

   } // end if
else
if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_DOWN]) 
   {
   // move skelaton
   skelaton.x-=2;
   skelaton.y+=2;
   dx=-2; dy=2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_SWEST)
      Set_Animation_BOB(&skelaton,SKELATON_SWEST);

   } // end if
else
if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_DOWN]) 
   {
   // move skelaton
   skelaton.x+=2;
   skelaton.y+=2;
   dx=2; dy=2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_SEAST)
      Set_Animation_BOB(&skelaton,SKELATON_SEAST);

   } // end if
else
if (keyboard_state[DIK_RIGHT]) 
   {
   // move skelaton
   skelaton.x+=2;
   dx=2; dy=0;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_EAST)
      Set_Animation_BOB(&skelaton,SKELATON_EAST);

   } // end if
else
if (keyboard_state[DIK_LEFT])  
   {
   // move skelaton
   skelaton.x-=2;
   dx=-2; dy=0; 
   
   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_WEST)
      Set_Animation_BOB(&skelaton,SKELATON_WEST);

   } // end if
else
if (keyboard_state[DIK_UP])    
   {
   // move skelaton
   skelaton.y-=2;
   dx=0; dy=-2;
   
   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_NORTH)
      Set_Animation_BOB(&skelaton,SKELATON_NORTH);

   } // end if
else
if (keyboard_state[DIK_DOWN])  
   {
   // move skelaton
   skelaton.y+=2;
   dx=0; dy=+2;

   // set motion flag
   player_moving = 1;

   // check animation needs to change
   if (skelaton.curr_animation != SKELATON_SOUTH)
      Set_Animation_BOB(&skelaton,SKELATON_SOUTH);

   } // end if

// only animate if player is moving
if (player_moving)
   {
   // animate skelaton
   Animate_BOB(&skelaton);


   // see if skelaton hit a wall
   
   // lock surface, so we can scan it
   DDraw_Lock_Back_Surface();
   
   // call the color scanner with WALL_ANIMATION_COLOR, the color of the glowing wall
   // try to center the scan in the center of the object to make it 
   // more realistic
   if (Color_Scan(skelaton.x+16, skelaton.y+16,
                  skelaton.x+skelaton.width-16, skelaton.y+skelaton.height-16,                                    
                  WALL_ANIMATION_COLOR, WALL_ANIMATION_COLOR, back_buffer,back_lpitch))
      {
      // back the skelaton up along its last trajectory
      skelaton.x-=dx;
      skelaton.y-=dy;
      } // end if
   
   // done, so unlock
   DDraw_Unlock_Back_Surface();

   // check if skelaton is off screen
   if (skelaton.x < 0 || skelaton.x > (screen_width - skelaton.width))
      skelaton.x-=dx;

   if (skelaton.y < 0 || skelaton.y > (screen_height - skelaton.height))
      skelaton.y-=dy;

   } // end if

// draw the skelaton
Draw_BOB(&skelaton, lpddsback);

// animate color
glow.peGreen+=glow_dx;

// test boundary
if (glow.peGreen == 0 || glow.peGreen == 255)
   glow_dx = -glow_dx;

Set_Palette_Entry(WALL_ANIMATION_COLOR, &glow);

// draw some text
Draw_Text_GDI("I STILL HAVE A BONE TO PICK!",0,screen_height - 32,WALL_ANIMATION_COLOR,lpddsback);

Draw_Text_GDI("USE ARROW KEYS TO MOVE, <ESC> TO EXIT.",0,0,RGB(32,32,32),lpddsback);


// flip the surfaces
DDraw_Flip();

// sync to 30ish fps
Wait_Clock(30);

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

    } // end if

// return success
return(1);
 
} // end Game_Main
示例#4
0
void Draw_Thread(ULONG ulThreadArg)
{
if(!(habDT=WinInitialize(0UL)))         /* Initialize client window */
    GEN_ERR(habDT,hwndFrame,hwndClient);
                                        /* Create a message queue */
if(!(hmqDT=WinCreateMsgQueue(habDT,0UL)))
    GEN_ERR(habDT,hwndFrame,hwndClient);
if(!(hpsDT=WinGetPS(hwndClient)))       /* Get a presentation space for client area */
    GEN_ERR(habDT,hwndFrame,hwndClient);
                                        /* Initialize message queue */
WinPostQueueMsg(hmqDT,DT_PAINT,0UL,0UL);
while(qmsqDT.msg!=DT_EXIT)
    {
    if(WinPeekMsg(habDT,                /* Get the message into message queue */
    &qmsqDT,                            /* Message structure */
    NULLHANDLE,                         /* Window filter (none) */
    0UL,                                /* First message ID */
    0UL,                                /* Last message ID */
    PM_REMOVE)==FALSE)                  /* Options (remove message) */
        qmsqDT.msg=DT_IDLE;             /* If no message available, assume idle */
    switch(qmsqDT.msg)
    {
    case DT_PAINT:                      /* Repaint client window */
        {
        RECTL   rclDT;
        int     x,y;
                                        /* Repaint client window aread */
        WinQueryWindowRect(hwndClient,&rclDT);
        WinFillRect(hpsDT,&rclDT,CLR_WHITE);
        for(x=1;x<RB_X;x++)             /* Draw the entries on playing ground */
            for(y=1;y<RB_Y;y++)
                if(RB_Array[x][y]!=RB_EMPTY)
                    Draw_Bitmap(RB_Array[x][y],ROP_SRCCOPY,(x-1)*RB_SIZE,(y-1)*RB_SIZE);
        break;
        }
    case DT_LBUTTON:
        {
        int     x,y;
                                        /* Left button was pressed, get the location,
                                           add \ to RB_Array, and draw \ bitmap, if
                                           field is emty */
        x=(LONGFROMMP(qmsqDT.mp1)/RB_SIZE)+1;
        y=(LONGFROMMP(qmsqDT.mp2)/RB_SIZE)+1;
        if(RB_Array[x][y]==RB_EMPTY)
            {
            RB_Array[x][y]=RB_LX;
            Draw_Bitmap(RB_LX,ROP_SRCCOPY,(x-1)*RB_SIZE,(y-1)*RB_SIZE);
            }
        break;
        }
    case DT_RBUTTON:
        {
        int     x,y;
                                        /* Right button was pressed, get the location,
                                           add / to RB_Array, and draw / bitmap, if
                                           field is emty */
        x=(LONGFROMMP(qmsqDT.mp1)/RB_SIZE)+1;
        y=(LONGFROMMP(qmsqDT.mp2)/RB_SIZE)+1;
        if(RB_Array[x][y]==RB_EMPTY)
            {
            RB_Array[x][y]=RB_RX;
            Draw_Bitmap(RB_RX,ROP_SRCCOPY,(x-1)*RB_SIZE,(y-1)*RB_SIZE);
            }
        break;
        }
     case DT_IDLE:
        {
        if(runRB==TRUE)
            {
            ULONG       x,y,Symbol;
                                        /* Under DOS we would query the time in milliseconds
                                           from the system timer, to adjust graphics. This
                                           is accurate, but in a multitasking in a multitasking
                                           system, we must assume being pre-empted. Therefore
                                           we can't have an exact time bases. Hope that
                                           the system timer counts more often than all 31
                                           milliseconds in future releases/machines */
                                        /* Draw bitmap */
            switch(RB_Dir)              /* Test that RollBall doesn't leave borders. A
                                           border reverses the direction and produces a
                                           beep */
            {
            case UP:
                RB_PosY++;
                if((RB_PosY+RB_SIZE)>=((RB_Y-2)*RB_SIZE))
                    {
                    RB_PosY=(RB_Y-3)*RB_SIZE;
                    RB_Dir=DOWN;
                    DosBeep(800,50);
                    }
                break;
            case DOWN:
                RB_PosY--;
                if(RB_PosY<0)
                    {
                    RB_PosY=0;
                    RB_Dir=UP;
                    DosBeep(800,50);
                    }
                break;
            case LEFT:
                RB_PosX--;
                if(RB_PosX<0)
                    {
                    RB_PosX=0;
                    RB_Dir=RIGHT;
                    DosBeep(800,50);
                    }
                break;
            case RIGHT:
                RB_PosX++;
                if((RB_PosX+RB_SIZE)>=((RB_X-2)*RB_SIZE))
                    {
                    RB_PosX=(RB_X-3)*RB_SIZE;
                    RB_Dir=LEFT;
                    DosBeep(800,50);
                    }
                break;
            }
                                        /* Draw RollBall at new position */
            Draw_Bitmap(RB_RB,ROP_SRCCOPY,RB_PosX,RB_PosY);
                                        /* Now, test if the middle of RollBall is over any
                                           symbol. If a symbol is found, add points, deflect
                                           or end game */
                                        /* RB_Array is 1 based, because 0 indices are the
                                           playing ground borders */
            x=((RB_PosX)/RB_SIZE)+1;
            y=((RB_PosY)/RB_SIZE)+1;
                                        /* A Symbol if RB_SIZE*RB_SIZE in size, that means
                                           RollBall is exactly over a symbol, if the lower
                                           left edges of both symbols match. Then, and only
                                           then, we count points, deflect or loose */
            if((RB_PosX==(x-1)*RB_SIZE) && (RB_PosY==(y-1)*RB_SIZE))
                Symbol=RB_Array[x][y];
            else Symbol=RB_EMPTY;
            switch(Symbol)
            {
            case RB_LX:                 /* We got a \ deflector */
                {
                switch(RB_Dir)          /* \ deflects direction of RollBall */
                {
                case RIGHT:
                    RB_Dir=DOWN; break;
                case UP:
                    RB_Dir=LEFT; break;
                case LEFT:
                    RB_Dir=UP; break;
                case DOWN:
                    RB_Dir=RIGHT; break;
                }                       /* Remove deflector */
                RB_Array[x][y]=RB_EMPTY;
                break;
                }
            case RB_RX:                 /* We got a / deflector */
                {
                switch(RB_Dir)          /* / deflects direction of RollBall */
                {
                case RIGHT:
                    RB_Dir=UP; break;
                case UP:
                    RB_Dir=RIGHT; break;
                case LEFT:
                    RB_Dir=DOWN; break;
                case DOWN:
                    RB_Dir=LEFT; break;
                }                       /* Remove deflector */
                RB_Array[x][y]=RB_EMPTY;
                DosBeep(600,20);
                break;
                }
            case RB_BP:                 /* We got a point */
            case RB_GP:
            case RB_MP:
            case RB_VP:
                {                       /* Add the points for each symbol */
                RB_Point[0]+=RB_Point[Symbol];
                                        /* Remove the point */
                RB_Array[x][y]=RB_EMPTY;
                if (ulDelay)
                    ulDelay--;
                DosBeep(700,20);
                break;
                }
            case RB_HOLE:               /* We got a hole, sorry but RollBall will be killed.
                                           We disable RollBall from rolling, and send a 
                                           ID_STOPTHREAD message to our window, which
                                           informs the user about the points with a message
                                           box */
                {
                int     freq;
                for(freq=5000;freq>100;freq-=100) DosBeep(freq,5);
                runRB=FALSE;            /* Prevent RollBall from further rolling */
                WinPostMsg(hwndClient,WM_COMMAND,(MPARAM)ID_STOPTHREAD,(MPARAM)0);
                break;
                }
            }
                                        /* Randomly add and remove symbols on playing ground */
            if((rand()%500)<2)
                {
                Put_Random_Field();
                Clear_Random_Field();
                }
            }
        }
    }
DosOpen("TIMER0$",
        &hfile,
        &ulAction,
        0,
        0,
        OPEN_ACTION_OPEN_IF_EXISTS,
        OPEN_FLAGS_FAIL_ON_ERROR | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE,
        NULL);   
ulDelay2=ulDelay/2;
DosDevIOCtl(hfile,
            HRT_IOCTL_CATEGORY,
            HRT_BLOCKUNTIL,
            &ulDelay2,
            ulSize2,
            &ulSize2,
            NULL,
            0,
            NULL);
DosClose(hfile);
}
WinReleasePS(hpsDT);                    /* Clean up */
WinDestroyMsgQueue(hmqDT);
WinTerminate(habDT);
DosExit(EXIT_THREAD,0UL);
}
int Game_Main(void *parms, int num_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


// check of user is trying to exit
if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))
    PostMessage(main_window_handle, WM_DESTROY,0,0);

// start the timing clock
Start_Clock();

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

// get the input from the mouse
lpdimouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mouse_state);

// move the mouse cursor
mouse_x+=(mouse_state.lX);
mouse_y+=(mouse_state.lY);

// test bounds

// first x boundaries
if (mouse_x >= screen_width)
   mouse_x = screen_width-1;
else
if (mouse_x < 0)
   mouse_x = 0;

// now the y boundaries
if (mouse_y >= screen_height)
   mouse_y= screen_height-1;
else
if (mouse_y < 0)
   mouse_y = 0;

// position the pointer bob to the mouse coords
pointer.x = mouse_x - 16;
pointer.y = mouse_y - 16;

// test what the user is doing with the mouse
if ((mouse_x > 3) && (mouse_x < 500-3) && 
    (mouse_y > 3) && (mouse_y < SCREEN_HEIGHT-3))
   {
   // mouse is within canvas region

   // if left button is down then draw
   if (mouse_state.rgbButtons[0])
      {
      // test drawing mode
      if (buttons_state[BUTTON_PENCIL])
         {
         // draw a pixel 
         Draw_Pixel(mouse_x, mouse_y, mouse_color, canvas.buffer, canvas.width);
         Draw_Pixel(mouse_x+1, mouse_y, mouse_color, canvas.buffer, canvas.width);
         Draw_Pixel(mouse_x, mouse_y+1, mouse_color, canvas.buffer, canvas.width);
         Draw_Pixel(mouse_x+1, mouse_y+1, mouse_color, canvas.buffer, canvas.width);
         }
      else
         {
         // draw spray
         for (index=0; index<10; index++)
             {
             // get next particle
             int sx=mouse_x-8+rand()%16;
             int sy=mouse_y-8+rand()%16;
            
             // make sure particle is in bounds
             if (sx > 0 && sx < 500 && sy > 0 && sy < screen_height)
                Draw_Pixel(sx, sy, mouse_color, canvas.buffer, canvas.width);
             } // end for index

         } // end else

      } // end if left button
    else // right button is eraser
    if (mouse_state.rgbButtons[1])
       {
       // test drawing mode
       if (buttons_state[BUTTON_PENCIL]) 
          {
          // erase a pixel 
          Draw_Pixel(mouse_x, mouse_y, 0, canvas.buffer, canvas.width);
          Draw_Pixel(mouse_x+1, mouse_y, 0, canvas.buffer, canvas.width);
          Draw_Pixel(mouse_x, mouse_y+1, 0, canvas.buffer, canvas.width);
          Draw_Pixel(mouse_x+1, mouse_y+1, 0, canvas.buffer, canvas.width);
          } // end if
       else
          {
          // erase spray
          for (index=0; index<20; index++)
              {
              // get next particle
              int sx=mouse_x-8+rand()%16;
              int sy=mouse_y-8+rand()%16;
            
              // make sure particle is in bounds
              if (sx > 0 && sx < 500 && sy > 0 && sy < screen_height)
                 Draw_Pixel(sx, sy, 0, canvas.buffer, canvas.width);
              } // end for index
          
          } // end else
       
       } // end if left button
  
   } // end if
else
if ( (mouse_x > 500+16) && (mouse_x < 500+16+8*9) &&
     (mouse_y > 8)      && (mouse_y < 8+32*9))
   {
   // within palette

   // test if button left button is down
   if (mouse_state.rgbButtons[0])
      {
      // see what color cell user is pointing to
      int cell_x = (mouse_x - (500+16))/9;
      int cell_y = (mouse_y - (8))/9;

      // change color
      mouse_color = cell_x + cell_y*8;

      } // end if
   } // end if
else
if ((mouse_x > 500) && (mouse_x < (500+100)) &&
    (mouse_y > 344) && (mouse_y < (383+34)) )
   {  
   // within button area
   // test for each button
   for (index=0; index<4; index++)
       {
       if ((mouse_x > buttons_x[index]) && (mouse_x < (buttons_x[index]+32)) &&
           (mouse_y > buttons_y[index]) && (mouse_y < (buttons_y[index]+34)) )
           break;

       } // end for

   // at this point we know where the user is, now determine what he
   // is doing with the buttons
   switch(index)
         {
         case BUTTON_SPRAY:
             {
             // if left button is down simply activate spray mode
             if (mouse_state.rgbButtons[0])
                {
                // depress button
                buttons_state[index] = 1;

               // de-activate pencil mode
                buttons_state[BUTTON_PENCIL] = 0;
                } // end if
             else
                {
                // make sure button is up
                // buttons_state[index] = 0;
                } // end else

             } break;
         
         case BUTTON_PENCIL:
             {
             // if left button is down activate spray mode
             if (mouse_state.rgbButtons[0])
                {
                // depress button
                buttons_state[index] = 1;

                // de-activate spray mode
                buttons_state[BUTTON_SPRAY] = 0;

                } // end if
             else
                {
                // make sure button is up
                // buttons_state[index] = 0;
                } // end else

             } break;

         case BUTTON_ERASE:
             {
             // test if left button is down, if so clear screen
             if (mouse_state.rgbButtons[0])
                {
                // clear memory
                memset(canvas.buffer,0,canvas.width*canvas.height);

                // depress button
                buttons_state[index] = 1;
                } // end if
             else
                {
                // make sure button is up
                buttons_state[index] = 0;
                } // end else
             } break;
         
         case BUTTON_EXIT:
             {
             // test if left button down, if so bail
             if (mouse_state.rgbButtons[0])
                  PostMessage(main_window_handle, WM_DESTROY,0,0);

             } break;

         } // end switch

   } // end if
else
   {
   // no mans land

   } // end else

// lock back buffer
DDraw_Lock_Back_Surface();

// draw the canvas
Draw_Bitmap(&canvas, back_buffer, back_lpitch,0);

// draw control panel
Draw_Bitmap(&cpanel,back_buffer,back_lpitch,0);

// unlock back buffer
DDraw_Unlock_Back_Surface();

// draw the color palette
for (int col=0; col < 256; col++)
    {
    Draw_Rectangle(500+16+(col%8)*9,   8+(col/8)*9,
                   500+16+(col%8)*9+8, 8+(col/8)*9+8,
                   col,lpddsback);
    
    } // end for col

// draw the current color selected
Draw_Rectangle(533,306,533+34,306+34,mouse_color,lpddsback);

// draw the buttons
for (index=0; index<4; index++)
    {
    // set position of button bob
    buttons.x = buttons_x[index];
    buttons.y = buttons_y[index];

    // now select the on/off frame based on if the
    // button is off
    if (buttons_state[index]==0)
        buttons.curr_frame = index;
    else // button is on
        buttons.curr_frame = index+4;

    // draw the button
    Draw_BOB(&buttons, lpddsback);

    } // end for index

static int green = 0;

// display coords
sprintf(buffer,"Pointer (%d,%d)",mouse_x,mouse_y);
Draw_Text_GDI(buffer, 8,screen_height - 16,RGB(0,255,0),lpddsback);
Draw_Text_GDI("T3D Paint Version 2.0 - Press <ESC> to Exit.",0,0,RGB(0,(green & 255),0),lpddsback);

// a little animation
++green;

// draw the cursor last
Draw_BOB(&pointer,lpddsback);

// flip the surfaces
DDraw_Flip();

// sync to 30 fps
Wait_Clock(30);

// return success
return(1);

} // end Game_Main
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

static int   curr_angle = 0; // current angle of elevation from horizon
static float curr_vel   = 10; // current velocity of projectile

// 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);

// do the graphics
Draw_Polygon2D(&cannon, back_buffer, back_lpitch);

// unlock back surface
DDraw_Unlock_Back_Surface();

// read keyboard
DInput_Read_Keyboard();

// test for rotate
if ((curr_angle < 90) && keyboard_state[DIK_UP]) // rotate left
   {
   Rotate_Polygon2D_Mat(&cannon, -5);
   curr_angle+=5;
   } // end if
else
if ((curr_angle > 0) &&keyboard_state[DIK_DOWN]) // rotate right
   {
   Rotate_Polygon2D_Mat(&cannon, 5);
   curr_angle-=5;
   } // end if

// test for projectile velocity
if (keyboard_state[DIK_RIGHT])  
   { 
   if (curr_vel < 30) curr_vel+=0.1;
   } // end if
else
if (keyboard_state[DIK_LEFT]) 
   { 
   if (curr_vel > 0) curr_vel-=0.1;
   } // end if

// test for wind force
if (keyboard_state[DIK_W])  
   { 
   if (wind_force < 2) wind_force+=0.01;
   } // end if
else
if (keyboard_state[DIK_E]) 
   { 
   if (wind_force > -2) wind_force-=0.01;
   } // end if

// test for gravity force
if (keyboard_state[DIK_G])  
   { 
   if (gravity_force < 15) gravity_force+=0.1;
   } // end if
else
if (keyboard_state[DIK_B]) 
   { 
   if (gravity_force > -15) gravity_force-=0.1;
   } // end if

// test for fire!
if (keyboard_state[DIK_LCONTROL]) 
   { 
   Fire_Projectile(curr_angle, curr_vel);

   } // end fire

// move all the projectiles
Move_Projectiles();

// draw the projectiles
Draw_Projectiles();

// draw the title
Draw_Text_GDI("Trajectory DEMO, Press <ESC> to Exit.",10, 10,RGB(255,255,255), lpddsback);
Draw_Text_GDI("<RIGHT>, <LEFT> to adjust velocity, <UP>, <DOWN> to adjust angle",10, 25, RGB(255,255,255), lpddsback);
Draw_Text_GDI("<G>, <B> to adjust gravity, <W>, <E> to adjust wind, <CTRL> to fire.",10, 40, RGB(255,255,255), lpddsback);

sprintf(buffer, "Ang=%d, Vel=%f", curr_angle, curr_vel);
Draw_Text_GDI(buffer,10, 60, RGB(255,255,255), lpddsback);

sprintf(buffer, "Wind force=%f, Gravity Force=%f", wind_force, gravity_force);
Draw_Text_GDI(buffer,10, 75, RGB(255,255,255), lpddsback);

// flip the surfaces
DDraw_Flip();

// 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_DARKNESS,NULL,0);
    } // end if

// return success
return(1);

} // end Game_Main
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
int          dx,dy;             // general deltas used in collision detection


// start the timing clock
Start_Clock();

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

// get the joystick data
DInput_Read_Joystick();

// lock the back buffer
DDraw_Lock_Back_Surface();

// draw the background reactor image
Draw_Bitmap(&playfield, back_buffer, back_lpitch, 0);

// unlock the back buffer
DDraw_Unlock_Back_Surface();

// is the player moving?
blaster.x+=joy_state.lX;
blaster.y+=joy_state.lY;

// test bounds
if (blaster.x > SCREEN_WIDTH-32)
    blaster.x = SCREEN_WIDTH-32;
else
if (blaster.x < 0)
    blaster.x = 0;

if (blaster.y > SCREEN_HEIGHT-32)
    blaster.y = SCREEN_HEIGHT-32;
else
if (blaster.y < SCREEN_HEIGHT-128)
    blaster.y = SCREEN_HEIGHT-128;

// is player firing?
if (joy_state.rgbButtons[0])
   Start_Missile();

// move and draw missle
Move_Missile();
Draw_Missile();

// is it time to blink eyes
if ((rand()%100)==50)
   Set_Animation_BOB(&blaster,0);

// draw blaster
Animate_BOB(&blaster);
Draw_BOB(&blaster,lpddsback);

// draw some text
Draw_Text_GDI("Make My Centipede!",0,0,RGB(255,255,255),lpddsback);

// display joystick and buttons 0-7
sprintf(buffer,"Joystick Stats: X-Axis=%d, Y-Axis=%d, buttons(%d,%d,%d,%d,%d,%d,%d,%d)",
                                                                      joy_state.lX,joy_state.lY,
                                                                      joy_state.rgbButtons[0],
                                                                      joy_state.rgbButtons[1],
                                                                      joy_state.rgbButtons[2],
                                                                      joy_state.rgbButtons[3],
                                                                      joy_state.rgbButtons[4],
                                                                      joy_state.rgbButtons[5],
                                                                      joy_state.rgbButtons[6],
                                                                      joy_state.rgbButtons[7]);

Draw_Text_GDI(buffer,0,SCREEN_HEIGHT-20,RGB(255,255,50),lpddsback);

// print out name of joystick
sprintf(buffer, "Joystick Name & Vendor: %s",joyname);
Draw_Text_GDI(buffer,0,SCREEN_HEIGHT-40,RGB(255,255,50),lpddsback);


// flip the surfaces
DDraw_Flip();

// sync to 30 fps
Wait_Clock(30);


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

    } // end if



// return success
return(1);

 
} // end Game_Main
int Game_Init(void *parms)
{
// this function is where you do all the initialization 
// for your game

int index; // looping var

// start up DirectDraw (replace the parms as you desire)
DDraw_Init(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP, WINDOWED_APP);

// initialize directinput
DInput_Init();

// acquire the keyboard 
DInput_Init_Keyboard();

// initialize the joystick
DInput_Init_Joystick(-24,24,-24,24);

// initialize directsound and directmusic
DSound_Init();
DMusic_Init();

// hide the mouse
ShowCursor(FALSE);

// seed random number generator
srand(Start_Clock());

// load the background
Load_Bitmap_File(&bitmap8bit, "MUSH.BMP");

// set the palette to background image palette
Set_Palette(bitmap8bit.palette);

// load in the four frames of the mushroom
for (index=0; index<4; index++)
    {
    // create mushroom bitmaps
    Create_Bitmap(&mushrooms[index],0,0,32,32);
    Load_Image_Bitmap(&mushrooms[index],&bitmap8bit,index,0,BITMAP_EXTRACT_MODE_CELL);  
    } // end for index

// now create the bug blaster bob
Create_BOB(&blaster,0,0,32,32,3,
           BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM | BOB_ATTR_ANIM_ONE_SHOT,
           DDSCAPS_SYSTEMMEMORY);

// load in the four frames of the mushroom
for (index=0; index<3; index++)
     Load_Frame_BOB(&blaster,&bitmap8bit,index,index,1,BITMAP_EXTRACT_MODE_CELL);  

// unload the bitmap file
Unload_Bitmap_File(&bitmap8bit);

// set the animation sequences for bug blaster
Load_Animation_BOB(&blaster,0,5,blaster_anim);

// set up stating state of bug blaster
Set_Pos_BOB(&blaster,320, 400);
Set_Anim_Speed_BOB(&blaster,3);

// set clipping rectangle to screen extents so objects dont
// mess up at edges
RECT screen_rect = {0,0,screen_width,screen_height};
lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);

// create mushroom playfield bitmap
Create_Bitmap(&playfield,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
playfield.attr |= BITMAP_ATTR_LOADED;

// fill in the background
Load_Bitmap_File(&bitmap8bit, "GRASS.BMP");

// load the grass bitmap image
Load_Image_Bitmap(&playfield,&bitmap8bit,0,0,BITMAP_EXTRACT_MODE_ABS);
Unload_Bitmap_File(&bitmap8bit);

// create the random mushroom patch
for (index=0; index<50; index++)
    {
    // select a mushroom
    int mush = rand()%4;

    // set mushroom to random position
    mushrooms[mush].x = rand()%(SCREEN_WIDTH-32);
    mushrooms[mush].y = rand()%(SCREEN_HEIGHT-128);

    // now draw the mushroom into playfield
    Draw_Bitmap(&mushrooms[mush], playfield.buffer, playfield.width,1);

    } // end for

// return success
return(1);

} // end Game_Init
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);

// unlock back surface
DDraw_Unlock_Back_Surface();

// read keyboard
DInput_Read_Keyboard();


// check the player controls

// is the player turning right or left?
if (keyboard_state[DIK_RIGHT])
   {
    // there are 16 possible positions for the ship to point in
    if (++ship.varsI[0] >= 16)
        ship.varsI[0] = 0;
   } // end if
else
if (keyboard_state[DIK_LEFT])
   {
    // there are 16 possible positions for the ship to point in
    if (--ship.varsI[0] < 0)
        ship.varsI[0] = 15;
   } // end if

// now test for forward thrust
if (keyboard_state[DIK_UP])
    {
    // thrust ship in current direction
    
    float rad_angle = (float)ship.varsI[0]*(float)3.14159/(float)8;
    float xv = cos(rad_angle);
    float yv = sin(rad_angle);

    ship.varsF[0]+=xv;
    ship.varsF[1]+=yv;

    // animate the ship
    ship.curr_frame = ship.varsI[0]+16*(rand()%2);

    } // end if
else // show non thrust version
   ship.curr_frame = ship.varsI[0];  

// move ship
ship.varsF[2]+=ship.varsF[0];
ship.varsF[3]+=ship.varsF[1];

// always apply friction in direction opposite current trajectory
float fx = -ship.varsF[0];
float fy = -ship.varsF[1];
float length_f = sqrt(fx*fx+fy*fy); // normally we would avoid square root at all costs!

// compute the frictional resitance

if (fabs(length_f) > 0.1)
    { 
    fx = FRICTION_FACTOR*fx/length_f;
    fy = FRICTION_FACTOR*fy/length_f;
    } // end if
else
    fx=fy=0;

// now apply friction to forward velocity
ship.varsF[0]+=fx;
ship.varsF[1]+=fy;

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

// gravity calculation section

// step 1: compute vector from black hole to ship, note that the centers
// of each object are used
float grav_x = (black_hole.x + black_hole.width/2)  - (ship.x + ship.width/2);
float grav_y = (black_hole.y + black_hole.height/2) - (ship.y + ship.height/2);
float radius_squared = grav_x*grav_x + grav_y*grav_y; // equal to radius squared
float length_grav = sqrt(radius_squared);

// step 2: normalize the length of the vector to 1.0
grav_x = grav_x/length_grav;
grav_y = grav_y/length_grav;

// step 3: compute the gravity force
float grav_force = (VIRTUAL_GRAVITY_CONSTANT) * (SHIP_MASS * BLACK_HOLE_MASS) / radius_squared;

// step 4: apply gforce in the direction of grav_x, grav_y with the magnitude of grav_force
ship.varsF[0]+=grav_x*grav_force;
ship.varsF[1]+=grav_y*grav_force;

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

// test if ship is off screen
if (ship.varsF[2] > SCREEN_WIDTH)
   ship.varsF[2] = -ship.width;
else
if (ship.varsF[2] < -ship.width)
   ship.varsF[2] = SCREEN_WIDTH;

if (ship.varsF[3] > SCREEN_HEIGHT)
   ship.varsF[3] = -ship.height;
else
if (ship.varsF[3] < -ship.height)
   ship.varsF[3] = SCREEN_HEIGHT;

// test if velocity is insane
if ( (ship.varsF[0]*ship.varsF[0] + ship.varsF[1]*ship.varsF[1]) > MAX_VEL)
   {
   // scale velocity down
   ship.varsF[0]*=.95;
   ship.varsF[1]*=.95;

   } // end if

// animate the black hole
Animate_BOB(&black_hole);

// draw the black hole
Draw_BOB(&black_hole, lpddsback);

// copy floating point position to bob x,y
ship.x = ship.varsF[2];
ship.y = ship.varsF[3];

// draw the ship
Draw_BOB(&ship,lpddsback);

// draw the title
Draw_Text_GDI("GRAVITY MASS DEMO - Use Arrows to Control Ship.",10, 10,RGB(0,255,255), lpddsback);

sprintf(buffer,"Friction: X=%f, Y=%f",fx, fy);
Draw_Text_GDI(buffer,10,420,RGB(0,255,0), lpddsback);

sprintf(buffer,"Velocity: X=%f, Y=%f",ship.varsF[0], ship.varsF[1]);
Draw_Text_GDI(buffer,10,440,RGB(0,255,0), lpddsback);

sprintf(buffer,"Gravity: X=%f, Y=%f",ship.varsF[2], ship.varsF[3]);
Draw_Text_GDI(buffer,10,460,RGB(0,255,0), lpddsback);

// flip the surfaces
DDraw_Flip();

// 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_DARKNESS,NULL,0);
    } // end if

// return success
return(1);

} // end Game_Main