1. ///   
  2.    
  3. int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap,     //位图文件扫描图像的数据来源   
  4.                       LPDIRECTDRAWSURFACE7 lpdds, // 锁定表面用的   
  5.                       int cx, int cy)             // 扫描图像的位置   
  6. {   
  7.     // this function extracts a bitmap out of a bitmap file   
  8.        
  9.     UCHAR *source_ptr,   // working pointers   
  10.                 *dest_ptr;   
  11.        
  12.     DDSURFACEDESC2 ddsd;  //  direct draw surface description    
  13.        
  14.     // get the addr to destination surface memory   
  15.        
  16.     // set size of the structure   
  17.     ddsd.dwSize = sizeof(ddsd);   
  18.        
  19.     // lock the display surface   
  20.     lpdds->Lock(NULL,   
  21.         &ddsd,   
  22.         DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,   
  23.         NULL);   
  24.        
  25.     // 计算开始扫描的位置   
  26.     cx = cx*(ddsd.dwWidth*4) ;   
  27.     cy = cy*(ddsd.dwHeight*4) ;   
  28.     //ddsd.dwWidth 以像素计算的表面 宽度       
  29.     //ddsd.dwHeight 以像素计算的表面 高度   
  30.     //表面占用字节= 宽*高*位深度占用字节   
  31.     //8位=1字节 16位=2字节 32位=4字节   
  32.    
  33.        
  34.     // 提取位图数据   
  35.     source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;   
  36.     //bitmap->buffer  指向位图数据的指针  等于数据开始的位置   
  37.     //bitmap->bitmapinfoheader.biWidth  位图的宽度,单位是像素,但缓冲区的定位是字节    
  38.     //32位图 每像素占用4字节   
  39.    
  40.     //   
  41.     //   
  42.     // assign a pointer to the memory surface for manipulation   
  43.     dest_ptr = (UCHAR *)ddsd.lpSurface;   
  44.        
  45.    
  46.         
  47.    
  48.         for (int index_y=0; index_y < ddsd.dwHeight*4; index_y++)   
  49.         {   
  50.        
  51.             // 复制下一行的数据到 目的地   
  52.             memcpy(dest_ptr, source_ptr, ddsd.dwWidth*4);//32位下每像素占4字节  gwidth  = ddsd.dwWidth*4;   
  53.    
  54.             // advance pointers   
  55.             dest_ptr   += (ddsd.lPitch); // 显示模式的水平内存艰巨,即每行的字节数 32位下等于ddsd.dwWidth*4   
  56.             source_ptr += bitmap->bitmapinfoheader.biWidth*4;//32位下每像素占4字节   
  57.             //bitmap->bitmapinfoheader.biWidth 位图的宽度,单位是像素,   
  58.         } // end for index_y   
  59.    
  60.        
  61.     // unlock the surface    
  62.     lpdds->Unlock(NULL);   
  63.        
  64.     // return success   
  65.     return(1);   
  66.        
  67. // end Scan_Image_Bitmap   
  68.    
  69. ///   
  70.    
  71.    
  72. ///   
  73.    
  74. LRESULT CALLBACK WindowProc(HWND hwnd,    
  75.                             UINT msg,    
  76.                             WPARAM wparam,    
  77.                             LPARAM lparam)   
  78. {   
  79.     // this is the main message handler of the system   
  80.     PAINTSTRUCT     ps;     // used in WM_PAINT   
  81.     HDC             hdc;    // handle to a device context   
  82.     char buffer[80];        // used to print strings   
  83.        
  84.     // what is the message    
  85.     switch(msg)   
  86.     {      
  87.     case WM_CREATE:    
  88.         {   
  89.             // do initialization stuff here   
  90.             // return success   
  91.             return(0);   
  92.         } break;   
  93.            
  94.     case WM_PAINT:    
  95.         {   
  96.             // simply validate the window    
  97.             hdc = BeginPaint(hwnd,&ps);     
  98.                
  99.             // end painting   
  100.             EndPaint(hwnd,&ps);   
  101.                
  102.             // return success   
  103.             return(0);   
  104.         } break;   
  105.            
  106.     case WM_DESTROY:    
  107.         {   
  108.                
  109.             // kill the application, this sends a WM_QUIT message    
  110.             PostQuitMessage(0);   
  111.                
  112.             // return success   
  113.             return(0);   
  114.         } break;   
  115.            
  116.     default:break;   
  117.            
  118.     } // end switch   
  119.        
  120.     // process any messages that we didn't take care of    
  121.     return (DefWindowProc(hwnd, msg, wparam, lparam));   
  122.        
  123. // end WinProc   
  124.    
  125. ///   
  126.    
  127. int Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE7 lpdds)   
  128. {   
  129.     // this function draws the sent text on the sent surface    
  130.     // using color index as the color in the palette   
  131.        
  132.     HDC xdc; // the working dc   
  133.        
  134.     // get the dc from surface   
  135.     if (FAILED(lpdds->GetDC(&xdc)))   
  136.         return(0);   
  137.        
  138.     // set the colors for the text up   
  139.     SetTextColor(xdc,color);   
  140.        
  141.     // set background mode to transparent so black isn't copied   
  142.     SetBkMode(xdc, TRANSPARENT);   
  143.        
  144.     // draw the text a   
  145.     TextOut(xdc,x,y,text,strlen(text));   
  146.        
  147.     // release the dc   
  148.     lpdds->ReleaseDC(xdc);   
  149.        
  150.     // return success   
  151.     return(1);   
  152. // end Draw_Text_GDI   
  153.    
  154. ///   
  155.    
  156. int Game_Main(void *parms = NULL, int num_parms = 0)   
  157. {   
  158.     // 这是主循环的游戏,做所有你在这里处理   
  159.    
  160.        
  161.     // 查找适当的步行序列   
  162.     static int animation_seq[4] = {0,1,0,2};   
  163.        
  164.     //开火序列   
  165.     static int animation_fire[4] ={0,1,2,1};   
  166.     //火球   
  167.     static int frie=6;   
  168.     int index; // 步行循环变量   
  169.        
  170.     // 确保这不是再次执行   
  171.     if (window_closed)   
  172.         return(0);   
  173.        
  174.     // 如果用户按下ESC 则立即发送  WM_CLOSE 关闭游戏   
  175.     if (KEYDOWN(VK_ESCAPE))   
  176.     {   
  177.         PostMessage(main_window_handle,WM_CLOSE,0,0);   
  178.         window_closed = 1;   
  179.     } // end if   
  180.        
  181.     // 从后备缓冲中复制背景   
  182.     DDraw_Draw_Surface(lpddsbackground,0,0, SCREEN_WIDTH,SCREEN_HEIGHT, lpddsback,0);       
  183.        
  184.     //自动控制   
  185.        
  186.     for (index=0; index < 2; index++)   
  187.     {   
  188.         // 向右移动每个对象在给定速度   
  189.         aliens[index].x++; // =aliens[index].velocity;   
  190.            
  191.          //测试是否进入屏幕的边缘,设置循环   
  192.         if (aliens[index].x > SCREEN_WIDTH)   
  193.             aliens[index].x = -40;//位移出屏幕外半个身位,重新进入时不突然   
  194.            
  195.         // 机器人前进   
  196.         //aliens[index].velocity 移动速度   
  197.         if (++aliens[index].counter >= (8 - aliens[index].velocity))  // aliens[index].velocity=2+0到3        即 2-5       8-2=6        8-5=3   
  198.         {   
  199.             //aliens[index].counter 动画占用时间   
  200.             //复位 counter   
  201.             aliens[index].counter = 0;   
  202.                
  203.             // 前进到下一帧   
  204.             if (++aliens[index].current_frame > 3)   
  205.                 aliens[index].current_frame = 0;   
  206.         }// end if   
  207.     }  // end for index   
  208.    
  209.     std::list::iterator iter=aliens_amm.begin();//指向容器第一个元素   
  210.        
  211.     for(iter=aliens_amm.begin();iter!=aliens_amm.end();)   
  212.     {   
  213.         if(iter->life==true)   
  214.             iter->x+=iter->velocity;   
  215.    
  216.    
  217.         if (iter->x > SCREEN_WIDTH )   
  218.         {   
  219.             iter->x = -40;//位移出屏幕外半个身位,重新进入时不突然   
  220.             iter->life=false;   
  221.             if(iter!=aliens_amm.end())   
  222.              iter=aliens_amm.erase(iter);   
  223.             //aliens_amm.pop_front();//删除最先发射的×××     
  224.         }   
  225.         else iter++;   
  226.     }   
  227.    
  228.          if((KEYDOWN(65)|KEYDOWN(97))) //按下A开火   
  229.     {   
  230.            
  231.          if(++aliens[2].counter_animation_fire>=5) // 开火动画时间   
  232.              {   
  233.                                 //复位计数器   
  234.                                 aliens[2].counter_animation_fire=0;//动画时间为0   
  235.                                 //前进到下一帧   
  236.                                 if (++aliens[2].current_animation_fire_frames>3)//当前帧大于3   
  237.                                 {   
  238.                                         aliens[2].current_animation_fire_frames=0;   
  239.                    
  240.                                         //动态插入×××链   
  241.                                         aa.life=true;   
  242.                                         aa.x=aliens[2].x + 40;   
  243.                                         aa.y=aliens[2].y+5;   
  244.                                         aa.velocity=6;   
  245.                                         aliens_amm.push_back(aa);   
  246.                            
  247.                                                
  248.                                            
  249.                                         }   
  250.                                 }   
  251.                
  252.    
  253.             DDraw_Draw_Surface(   aliens[2].animation_fire_frames[   animation_fire [ aliens[2].current_animation_fire_frames  ]  ], // 要画的源表面   
  254.                 aliens[2].x, aliens[2].y, // 要绘制的位置   
  255.                 74,82,// 源表面的尺寸   
  256.                 lpddsback);// 要画的目标表面   
  257.             //设置弹药数据   
  258.            
  259.        
  260.             for(iter=aliens_amm.begin();iter!=aliens_amm.end();iter++)   
  261.             {   
  262.                    
  263.             //画出所有弹药   
  264.             DDraw_Draw_Surface(   aliens[2].fire_frames, // 要画的源表面   
  265.                 iter->x, iter->y, // 要绘制的位置   
  266.                 74,82,// 源表面的尺寸   
  267.                 lpddsback);// 要画的目标表面   
  268.             }   
  269.    }//end if   
  270.    
  271.   else if (  KEYDOWN(VK_RIGHT) )//向右移动   
  272.     {   
  273.            
  274.                 aliens[2].x++;   
  275.              //测试是否进入屏幕的边缘,设置循环   
  276.                   if(aliens[2].x>SCREEN_WIDTH)   
  277.                       aliens[2].x=-40;   
  278.                   if (++aliens[2].counter >=(8-aliens[2].velocity)) // aliens[index].velocity=2+0到3        即 2-5       8-2=6        8-5=3   
  279.                         {   
  280.                                 //复位计数器   
  281.                                 aliens[2].counter=0;//动画时间为0   
  282.                                 //前进到下一帧   
  283.                                 if (++aliens[2].current_frame>3)//当前帧大于3   
  284.                                         aliens[2].current_frame=0;   
  285.                           }//end if   
  286.     
  287.    
  288.             // 画手动控制的机器人   
  289.         DDraw_Draw_Surface(   aliens[2].frames[      animation_seq  [          aliens[2].current_frame   ]     ], // 要画的源表面   
  290.             aliens[2].x, aliens[2].y, // 要绘制的位置   
  291.             74,82,// 源表面的尺寸   
  292.             lpddsback);// 要画的目标表面   
  293.        
  294.        /*  
  295.         *LPDIRECTDRAWSURFACE7 frames[3]; 主表面接口绘图  
  296.         *aliens[index].frames[ index]三帧的动画完整步行周期  
  297.         *animation_seq[index] = {0,1,0,2};  
  298.         *aliens[index].current_frame]// 当前帧的动画  
  299.         */   
  300.    
  301.   }   
  302. else    
  303. {  //当没有按下开火或者移动指令   
  304.    
  305.     
  306.    
  307.             // 画手动控制的机器人   
  308.         DDraw_Draw_Surface(   aliens[2].frames[      animation_seq  [          aliens[2].current_frame   ]     ], // 要画的源表面   
  309.             aliens[2].x, aliens[2].y, // 要绘制的位置   
  310.             74,82,// 源表面的尺寸   
  311.             lpddsback);// 要画的目标表面   
  312.    
  313. }   
  314.   for(iter=aliens_amm.begin();iter!=aliens_amm.end();iter++)   
  315. {   
  316.       if(iter->life==true)   
  317.       {   
  318.                 //弹药   
  319.                 DDraw_Draw_Surface(   aliens[2].fire_frames, // 要画的源表面   
  320.                     iter->x, iter->y, // 要绘制的位置   
  321.                     74,82,// 源表面的尺寸   
  322.                     lpddsback);// 要画的目标表面   
  323.       }   
  324.   }   
  325.     // 画出1.2行的机器人   
  326.     for (index=0; index < 2; index++)   
  327.     {   
  328.         // 画对象   
  329.         DDraw_Draw_Surface(   aliens[index].frames[      animation_seq  [          aliens[index].current_frame   ]     ], // 要画的源表面   
  330.             aliens[index].x, aliens[index].y, // 要绘制的位置   
  331.             74,82,// 源表面的尺寸   
  332.             lpddsback);// 要画的目标表面   
  333.    
  334.        /*  
  335.         *LPDIRECTDRAWSURFACE7 frames[3]; 主表面接口绘图  
  336.         *aliens[index].frames[ index]三帧的动画完整步行周期  
  337.         *animation_seq[index] = {0,1,0,2};  
  338.         *aliens[index].current_frame]// 当前帧的动画  
  339.         */   
  340.     } // end for index   
  341.            
  342.    
  343.     //开火动画   按下A或者a   
  344.    
  345.     // 将主表面与后备缓冲表面切换  注意,调用前要确保主表面和后备缓冲表面都必须 被解锁   
  346.     while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));   
  347.        
  348.     // wait a sec   
  349.     Sleep(30);   
  350.        
  351.     // return success or failure or your own return code here   
  352.     return(1);   
  353.        
  354. // end Game_Main   
  355.    
  356.    
  357.    
  358. int Game_Init(void *parms = NULL, int num_parms = 0)   
  359. {   
  360.     // this is called once after the initial window is created and   
  361.     // before the main event loop is entered, do all your initialization   
  362.     // here   
  363.     int index;   
  364.     // create IDirectDraw interface 7.0 object and test for error   
  365.     if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))   
  366.         return(0);   
  367.     // set cooperation to full screen   
  368.     if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,    
  369.         DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |    
  370.         DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))   
  371.         return(0);   
  372.        
  373.     // set display mode to 640x480x32   
  374.     if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))   
  375.         return(0);   
  376.        
  377.     // we need a complex surface system with a primary and backbuffer   
  378.        
  379.     // clear ddsd and set size   
  380.     DDRAW_INIT_STRUCT(ddsd);    
  381.        
  382.     // enable valid fields   
  383.     ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;   
  384.        
  385.     // set the backbuffer count field to 1, use 2 for triple buffering   
  386.     ddsd.dwBackBufferCount = 1;   
  387.        
  388.     // request a complex, flippable   
  389.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |   
  390.                                              DDSCAPS_COMPLEX | DDSCAPS_FLIP;   
  391.        
  392.     // create the primary surface   
  393.     if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))   
  394.         return(0);   
  395.        
  396.     // now query for attached surface from the primary surface   
  397.        
  398.     // this line is needed by the call   
  399.     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;   
  400.        
  401.     // 获取后备缓冲区的指针   
  402.     if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))   
  403.         return(0);   
  404.    
  405.        
  406.     // set clipper up on back buffer since that's where well clip   
  407.     RECT screen_rect= {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1};   
  408.     lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);   
  409.        
  410.     // 读取位图   
  411.     if (!Load_Bitmap_File(&bitmap,ALLEY))   
  412.         return(0);   
  413.    
  414.    
  415.     // 清空表面   
  416.     DDraw_Fill_Surface(lpddsprimary,0);   
  417.     DDraw_Fill_Surface(lpddsback,0);   
  418.        
  419.     // create the buffer to hold the background   
  420.     lpddsbackground = DDraw_Create_Surface(640,480,0);    
  421.        
  422.     // copy the background bitmap p_w_picpath to the background surface    
  423.        
  424.     // 锁定表面   
  425.     lpddsbackground->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);   
  426.        
  427.     //获取主表面的显示指针   
  428.     UCHAR *p_w_picpath_buffer = (UCHAR *)ddsd.lpSurface;          
  429.    
  430.    
  431.     // 如果内存是线性的   
  432.     if (ddsd.lPitch == (SCREEN_WIDTH*4)) //32 位下每像素4字节 640X4   
  433.     {   
  434.         // copy memory from double buffer to primary buffer   
  435.         memcpy((void *)p_w_picpath_buffer, (void *)bitmap.buffer, SCREEN_WIDTH*SCREEN_HEIGHT*4);   
  436.     } // end if   
  437.     else   
  438.     { // non-linear   
  439.            
  440.         // make copy of source and destination addresses   
  441.         UCHAR *dest_ptr = p_w_picpath_buffer;   
  442.         UCHAR *src_ptr  = bitmap.buffer;   
  443.            
  444.         // memory is non-linear, copy line by line   
  445.         for (int y=0; y < SCREEN_HEIGHT; y++)   
  446.         {   
  447.             // copy line   
  448.             memcpy((void *)dest_ptr, (void *)src_ptr, SCREEN_WIDTH*4);   
  449.                
  450.             // advance pointers to next line   
  451.             dest_ptr+=ddsd.lPitch;   
  452.             src_ptr +=SCREEN_WIDTH;   
  453.         } // end for   
  454.            
  455.     } // end else   
  456.    
  457.     // now unlock the primary surface   
  458.     if (FAILED(lpddsbackground->Unlock(NULL)))   
  459.         return(0);   
  460.        
  461.     // unload the bitmap file, we no longer need it   
  462.     Unload_Bitmap_File(&bitmap);   
  463.        
  464.     // seed random number generator   
  465.     srand(GetTickCount());   
  466.        
  467.     // initialize all the aliens   
  468.        
  469.     // alien on level 1 of complex   
  470.        
  471.     aliens[0].x              = rand()%SCREEN_WIDTH;   
  472.     aliens[0].y              = 116 - 72;                     
  473.     aliens[0].velocity       = 2+rand()%4;   
  474.     aliens[0].current_frame  = 0;                
  475.     aliens[0].counter        = 0;          
  476.        
  477.     // alien on level 2 of complex   
  478.        
  479.     aliens[1].x              = rand()%SCREEN_WIDTH;   
  480.     aliens[1].y              = 246 - 72;                     
  481.     aliens[1].velocity       = 2+rand()%4;   
  482.     aliens[1].current_frame  = 0;                
  483.     aliens[1].counter        = 0;     
  484.        
  485.     // alien on level 3 of complex   
  486.        
  487.     aliens[2].x              = rand()%SCREEN_WIDTH;   
  488.     aliens[2].y              = 382 - 72;                     
  489.     aliens[2].velocity       = 2+rand()%4;   
  490.     aliens[2].current_frame  = 0;    
  491.     aliens[2].current_animation_fire_frames=0;   
  492.     aliens[2].counter        = 0;     
  493.     aliens[2].counter_animation_fire=0;   
  494.    
  495. //初始化弹药   
  496.        
  497.        
  498.    
  499.     
  500.    
  501.    
  502.     // 现在加载包含外星人的位图   
  503.     // 然后扫描图像到 alien[0]的表面   
  504.     // 然后负责到另外2个那里, 但要小心引用计数!   
  505.    
  506.        
  507.     // 读取32位图   
  508.     if (!Load_Bitmap_File(&bitmap,DEDSP))   
  509.         return(0);   
  510.    
  511.     // 生成动画每帧的表面   
  512.     for ( index = 0; index < 3; index++)   
  513.     {   
  514.         // 创建存储图像的表面   
  515.         aliens[0].frames[index] = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY);  //DDSCAPS_VIDEOMEMORY 创建在显存中   
  516.            
  517.         // 加载位图   
  518.         Scan_Image_Bitmap(&bitmap,                 // 要加载的位图文件数据来源   
  519.             aliens[0].frames[index], // 保存数据的表面   
  520.             index, 0);               // 扫描图像的单元 x,y   实际扫描是X*74  即一格图   
  521.            
  522.     } // end for index   
  523.    
  524.     //生成开火动画每帧的表面   
  525. for ( index = 0; index < 3; index++)   
  526.     {   
  527.         // 创建存储图像的表面   
  528.         aliens[2].animation_fire_frames[index] = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY);   //DDSCAPS_VIDEOMEMORY 创建在显存中   
  529.            
  530.         // 加载位图   
  531.         Scan_Image_Bitmap(&bitmap,                 // 要加载的位图文件数据来源   
  532.             aliens[2].animation_fire_frames[index], // 保存数据的表面   
  533.             index, 1);               // 扫描图像的单元 x,y坐标   实际扫描是X*74  即一格图 y*82   
  534.            
  535.     } // end for index   
  536.    
  537. //生成存储火球×××的表面   
  538. // 创建存储图像的表面   
  539.         aliens[2].fire_frames = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY);    //DDSCAPS_VIDEOMEMORY 创建在显存中   
  540.            
  541.         // 加载位图   
  542.         Scan_Image_Bitmap(&bitmap,                 // 要加载的位图文件数据来源   
  543.             aliens[2].fire_frames, // 保存数据的表面   
  544.             3, 1);               // 扫描图像的单元 x,y坐标   实际扫描是X*74  即一格图 y*82   
  545.            
  546.        
  547.     // unload the bitmap file, we no longer need it   
  548.     Unload_Bitmap_File(&bitmap);   
  549.        
  550.     // now for the tricky part. There is no need to create more surfaces with the same   
  551.     // data, so I'm going to copy the surface pointers member for member to each alien   
  552.     // however, be careful, since the reference counts do NOT go up, you still only need   
  553.     // to release() each surface once!   
  554.        
  555.     for (index = 0; index < 3; index++)   
  556.         aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index];   
  557.        
  558.     // return success or failure or your own return code here   
  559.     return(1);   
  560.        
  561. // end Game_Init   
  562.    
  563.