- ///////////////////////////////////////////////////////////////
- int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, //位圖文件掃描圖像的數據來源
- LPDIRECTDRAWSURFACE7 lpdds, // 鎖定表面用的
- int cx, int cy) // 掃描圖像的位置
- {
- // this function extracts a bitmap out of a bitmap file
- UCHAR *source_ptr, // working pointers
- *dest_ptr;
- DDSURFACEDESC2 ddsd; // direct draw surface description
- // get the addr to destination surface memory
- // set size of the structure
- ddsd.dwSize = sizeof(ddsd);
- // lock the display surface
- lpdds->Lock(NULL,
- &ddsd,
- DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
- NULL);
- // 計算開始掃描的位置
- cx = cx*(ddsd.dwWidth*4) ;
- cy = cy*(ddsd.dwHeight*4) ;
- //ddsd.dwWidth 以像素計算的表面 寬度
- //ddsd.dwHeight 以像素計算的表面 高度
- //表面佔用字節= 寬*高*位深度佔用字節
- //8位=1字節 16位=2字節 32位=4字節
- // 提取位圖數據
- source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;
- //bitmap->buffer 指向位圖數據的指針 等於數據開始的位置
- //bitmap->bitmapinfoheader.biWidth 位圖的寬度,單位是像素,但緩衝區的定位是字節
- //32位圖 每像素佔用4字節
- //
- //
- // assign a pointer to the memory surface for manipulation
- dest_ptr = (UCHAR *)ddsd.lpSurface;
- for (int index_y=0; index_y < ddsd.dwHeight*4; index_y++)
- {
- // 複製下一行的數據到 目的地
- memcpy(dest_ptr, source_ptr, ddsd.dwWidth*4);//32位下每像素佔4字節 gwidth = ddsd.dwWidth*4;
- // advance pointers
- dest_ptr += (ddsd.lPitch); // 顯示模式的水平內存艱鉅,即每行的字節數 32位下等於ddsd.dwWidth*4
- source_ptr += bitmap->bitmapinfoheader.biWidth*4;//32位下每像素佔4字節
- //bitmap->bitmapinfoheader.biWidth 位圖的寬度,單位是像素,
- } // end for index_y
- // unlock the surface
- lpdds->Unlock(NULL);
- // return success
- return(1);
- } // end Scan_Image_Bitmap
- ///////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////
- LRESULT CALLBACK WindowProc(HWND hwnd,
- UINT msg,
- WPARAM wparam,
- LPARAM lparam)
- {
- // this is the main message handler of the system
- PAINTSTRUCT ps; // used in WM_PAINT
- HDC hdc; // handle to a device context
- char buffer[80]; // used to print strings
- // what is the message
- switch(msg)
- {
- case WM_CREATE:
- {
- // do initialization stuff here
- // return success
- return(0);
- } break;
- case WM_PAINT:
- {
- // simply validate the window
- hdc = BeginPaint(hwnd,&ps);
- // end painting
- EndPaint(hwnd,&ps);
- // return success
- return(0);
- } break;
- case WM_DESTROY:
- {
- // kill the application, this sends a WM_QUIT message
- PostQuitMessage(0);
- // return success
- return(0);
- } break;
- default:break;
- } // end switch
- // process any messages that we didn't take care of
- return (DefWindowProc(hwnd, msg, wparam, lparam));
- } // end WinProc
- ///////////////////////////////////////////////////////////
- int Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE7 lpdds)
- {
- // this function draws the sent text on the sent surface
- // using color index as the color in the palette
- HDC xdc; // the working dc
- // get the dc from surface
- if (FAILED(lpdds->GetDC(&xdc)))
- return(0);
- // set the colors for the text up
- SetTextColor(xdc,color);
- // set background mode to transparent so black isn't copied
- SetBkMode(xdc, TRANSPARENT);
- // draw the text a
- TextOut(xdc,x,y,text,strlen(text));
- // release the dc
- lpdds->ReleaseDC(xdc);
- // return success
- return(1);
- } // end Draw_Text_GDI
- ///////////////////////////////////////////////////////////////
- int Game_Main(void *parms = NULL, int num_parms = 0)
- {
- // 這是主循環的遊戲,作全部你在這裏處理
- // 查找適當的步行序列
- static int animation_seq[4] = {0,1,0,2};
- //開火序列
- static int animation_fire[4] ={0,1,2,1};
- //火球
- static int frie=6;
- int index; // 步行循環變量
- // 確保這不是再次執行
- if (window_closed)
- return(0);
- // 若是用戶按下ESC 則當即發送 WM_CLOSE 關閉遊戲
- if (KEYDOWN(VK_ESCAPE))
- {
- PostMessage(main_window_handle,WM_CLOSE,0,0);
- window_closed = 1;
- } // end if
- // 從後備緩衝中複製背景
- DDraw_Draw_Surface(lpddsbackground,0,0, SCREEN_WIDTH,SCREEN_HEIGHT, lpddsback,0);
- //自動控制
- for (index=0; index < 2; index++)
- {
- // 向右移動每一個對象在給定速度
- aliens[index].x++; // =aliens[index].velocity;
- //測試是否進入屏幕的邊緣,設置循環
- if (aliens[index].x > SCREEN_WIDTH)
- aliens[index].x = -40;//位移出屏幕外半個身位,從新進入時不忽然
- // 機器人前進
- //aliens[index].velocity 移動速度
- if (++aliens[index].counter >= (8 - aliens[index].velocity)) // aliens[index].velocity=2+0到3 即 2-5 8-2=6 8-5=3
- {
- //aliens[index].counter 動畫佔用時間
- //復位 counter
- aliens[index].counter = 0;
- // 前進到下一幀
- if (++aliens[index].current_frame > 3)
- aliens[index].current_frame = 0;
- }// end if
- } // end for index
- std::list<ALIEN_AMM>::iterator iter=aliens_amm.begin();//指向容器第一個元素
- for(iter=aliens_amm.begin();iter!=aliens_amm.end();)
- {
- if(iter->life==true)
- iter->x+=iter->velocity;
- if (iter->x > SCREEN_WIDTH )
- {
- iter->x = -40;//位移出屏幕外半個身位,從新進入時不忽然
- iter->life=false;
- if(iter!=aliens_amm.end())
- iter=aliens_amm.erase(iter);
- //aliens_amm.pop_front();//刪除最早發射的×××
- }
- else iter++;
- }
- if((KEYDOWN(65)|KEYDOWN(97))) //按下A開火
- {
- if(++aliens[2].counter_animation_fire>=5) // 開火動畫時間
- {
- //復位計數器
- aliens[2].counter_animation_fire=0;//動畫時間爲0
- //前進到下一幀
- if (++aliens[2].current_animation_fire_frames>3)//當前幀大於3
- {
- aliens[2].current_animation_fire_frames=0;
- //動態插入×××鏈
- aa.life=true;
- aa.x=aliens[2].x + 40;
- aa.y=aliens[2].y+5;
- aa.velocity=6;
- aliens_amm.push_back(aa);
- }
- }
- DDraw_Draw_Surface( aliens[2].animation_fire_frames[ animation_fire [ aliens[2].current_animation_fire_frames ] ], // 要畫的源表面
- aliens[2].x, aliens[2].y, // 要繪製的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要畫的目標表面
- //設置彈藥數據
- for(iter=aliens_amm.begin();iter!=aliens_amm.end();iter++)
- {
- //畫出全部彈藥
- DDraw_Draw_Surface( aliens[2].fire_frames, // 要畫的源表面
- iter->x, iter->y, // 要繪製的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要畫的目標表面
- }
- }//end if
- else if ( KEYDOWN(VK_RIGHT) )//向右移動
- {
- aliens[2].x++;
- //測試是否進入屏幕的邊緣,設置循環
- if(aliens[2].x>SCREEN_WIDTH)
- aliens[2].x=-40;
- if (++aliens[2].counter >=(8-aliens[2].velocity)) // aliens[index].velocity=2+0到3 即 2-5 8-2=6 8-5=3
- {
- //復位計數器
- aliens[2].counter=0;//動畫時間爲0
- //前進到下一幀
- if (++aliens[2].current_frame>3)//當前幀大於3
- aliens[2].current_frame=0;
- }//end if
- // 畫手動控制的機器人
- DDraw_Draw_Surface( aliens[2].frames[ animation_seq [ aliens[2].current_frame ] ], // 要畫的源表面
- aliens[2].x, aliens[2].y, // 要繪製的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要畫的目標表面
- /*
- *LPDIRECTDRAWSURFACE7 frames[3]; 主表面接口繪圖
- *aliens[index].frames[ index]三幀的動畫完整步行週期
- *animation_seq[index] = {0,1,0,2};
- *aliens[index].current_frame]// 當前幀的動畫
- */
- }
- else
- { //當沒有按下開火或者移動指令
- // 畫手動控制的機器人
- DDraw_Draw_Surface( aliens[2].frames[ animation_seq [ aliens[2].current_frame ] ], // 要畫的源表面
- aliens[2].x, aliens[2].y, // 要繪製的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要畫的目標表面
- }
- for(iter=aliens_amm.begin();iter!=aliens_amm.end();iter++)
- {
- if(iter->life==true)
- {
- //彈藥
- DDraw_Draw_Surface( aliens[2].fire_frames, // 要畫的源表面
- iter->x, iter->y, // 要繪製的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要畫的目標表面
- }
- }
- // 畫出1.2行的機器人
- for (index=0; index < 2; index++)
- {
- // 畫對象
- DDraw_Draw_Surface( aliens[index].frames[ animation_seq [ aliens[index].current_frame ] ], // 要畫的源表面
- aliens[index].x, aliens[index].y, // 要繪製的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要畫的目標表面
- /*
- *LPDIRECTDRAWSURFACE7 frames[3]; 主表面接口繪圖
- *aliens[index].frames[ index]三幀的動畫完整步行週期
- *animation_seq[index] = {0,1,0,2};
- *aliens[index].current_frame]// 當前幀的動畫
- */
- } // end for index
- //開火動畫 按下A或者a
- // 將主表面與後備緩衝表面切換 注意,調用前要確保主表面和後備緩衝表面都必須 被解鎖
- while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));
- // wait a sec
- Sleep(30);
- // return success or failure or your own return code here
- return(1);
- } // end Game_Main
- ////////////////////////////////////////////////////////////
- int Game_Init(void *parms = NULL, int num_parms = 0)
- {
- // this is called once after the initial window is created and
- // before the main event loop is entered, do all your initialization
- // here
- int index;
- // create IDirectDraw interface 7.0 object and test for error
- if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
- return(0);
- // set cooperation to full screen
- if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,
- DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |
- DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
- return(0);
- // set display mode to 640x480x32
- if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
- return(0);
- // we need a complex surface system with a primary and backbuffer
- // clear ddsd and set size
- DDRAW_INIT_STRUCT(ddsd);
- // enable valid fields
- ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
- // set the backbuffer count field to 1, use 2 for triple buffering
- ddsd.dwBackBufferCount = 1;
- // request a complex, flippable
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
- DDSCAPS_COMPLEX | DDSCAPS_FLIP;
- // create the primary surface
- if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
- return(0);
- // now query for attached surface from the primary surface
- // this line is needed by the call
- ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
- // 獲取後備緩衝區的指針
- if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
- return(0);
- // set clipper up on back buffer since that's where well clip
- RECT screen_rect= {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1};
- lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);
- // 讀取位圖
- if (!Load_Bitmap_File(&bitmap,ALLEY))
- return(0);
- // 清空表面
- DDraw_Fill_Surface(lpddsprimary,0);
- DDraw_Fill_Surface(lpddsback,0);
- // create the buffer to hold the background
- lpddsbackground = DDraw_Create_Surface(640,480,0);
- // copy the background bitmap p_w_picpath to the background surface
- // 鎖定表面
- lpddsbackground->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
- //獲取主表面的顯示指針
- UCHAR *p_w_picpath_buffer = (UCHAR *)ddsd.lpSurface;
- // 若是內存是線性的
- if (ddsd.lPitch == (SCREEN_WIDTH*4)) //32 位下每像素4字節 640X4
- {
- // copy memory from double buffer to primary buffer
- memcpy((void *)p_w_picpath_buffer, (void *)bitmap.buffer, SCREEN_WIDTH*SCREEN_HEIGHT*4);
- } // end if
- else
- { // non-linear
- // make copy of source and destination addresses
- UCHAR *dest_ptr = p_w_picpath_buffer;
- UCHAR *src_ptr = bitmap.buffer;
- // memory is non-linear, copy line by line
- for (int y=0; y < SCREEN_HEIGHT; y++)
- {
- // copy line
- memcpy((void *)dest_ptr, (void *)src_ptr, SCREEN_WIDTH*4);
- // advance pointers to next line
- dest_ptr+=ddsd.lPitch;
- src_ptr +=SCREEN_WIDTH;
- } // end for
- } // end else
- // now unlock the primary surface
- if (FAILED(lpddsbackground->Unlock(NULL)))
- return(0);
- // unload the bitmap file, we no longer need it
- Unload_Bitmap_File(&bitmap);
- // seed random number generator
- srand(GetTickCount());
- // initialize all the aliens
- // alien on level 1 of complex
- aliens[0].x = rand()%SCREEN_WIDTH;
- aliens[0].y = 116 - 72;
- aliens[0].velocity = 2+rand()%4;
- aliens[0].current_frame = 0;
- aliens[0].counter = 0;
- // alien on level 2 of complex
- aliens[1].x = rand()%SCREEN_WIDTH;
- aliens[1].y = 246 - 72;
- aliens[1].velocity = 2+rand()%4;
- aliens[1].current_frame = 0;
- aliens[1].counter = 0;
- // alien on level 3 of complex
- aliens[2].x = rand()%SCREEN_WIDTH;
- aliens[2].y = 382 - 72;
- aliens[2].velocity = 2+rand()%4;
- aliens[2].current_frame = 0;
- aliens[2].current_animation_fire_frames=0;
- aliens[2].counter = 0;
- aliens[2].counter_animation_fire=0;
- //初始化彈藥
- // 如今加載包含外星人的位圖
- // 而後掃描圖像到 alien[0]的表面
- // 而後負責到另外2個那裏, 但要當心引用計數!
- // 讀取32位圖
- if (!Load_Bitmap_File(&bitmap,DEDSP))
- return(0);
- // 生成動畫每幀的表面
- for ( index = 0; index < 3; index++)
- {
- // 建立存儲圖像的表面
- aliens[0].frames[index] = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY); //DDSCAPS_VIDEOMEMORY 建立在顯存中
- // 加載位圖
- Scan_Image_Bitmap(&bitmap, // 要加載的位圖文件數據來源
- aliens[0].frames[index], // 保存數據的表面
- index, 0); // 掃描圖像的單元 x,y 實際掃描是X*74 即一格圖
- } // end for index
- //生成開火動畫每幀的表面
- for ( index = 0; index < 3; index++)
- {
- // 建立存儲圖像的表面
- aliens[2].animation_fire_frames[index] = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY); //DDSCAPS_VIDEOMEMORY 建立在顯存中
- // 加載位圖
- Scan_Image_Bitmap(&bitmap, // 要加載的位圖文件數據來源
- aliens[2].animation_fire_frames[index], // 保存數據的表面
- index, 1); // 掃描圖像的單元 x,y座標 實際掃描是X*74 即一格圖 y*82
- } // end for index
- //生成存儲火球×××的表面
- // 建立存儲圖像的表面
- aliens[2].fire_frames = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY); //DDSCAPS_VIDEOMEMORY 建立在顯存中
- // 加載位圖
- Scan_Image_Bitmap(&bitmap, // 要加載的位圖文件數據來源
- aliens[2].fire_frames, // 保存數據的表面
- 3, 1); // 掃描圖像的單元 x,y座標 實際掃描是X*74 即一格圖 y*82
- // unload the bitmap file, we no longer need it
- Unload_Bitmap_File(&bitmap);
- // now for the tricky part. There is no need to create more surfaces with the same
- // data, so I'm going to copy the surface pointers member for member to each alien
- // however, be careful, since the reference counts do NOT go up, you still only need
- // to release() each surface once!
- for (index = 0; index < 3; index++)
- aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index];
- // return success or failure or your own return code here
- return(1);
- } // end Game_Init
- ////////////////////////////////////////////////////////////