home *** CD-ROM | disk | FTP | other *** search
/ Oh!X 2001 Spring / Oh!X 2001 Spring Special CD-ROM (Japan) (Track 1).bin / DX8VC / PingPong / PingPong.cpp next >
Encoding:
C/C++ Source or Header  |  2001-01-07  |  8.2 KB  |  352 lines

  1. // DirectDraw サンプルゲーム
  2. // PingPong.cpp
  3.  
  4. #include "stdafx.h"
  5. #include "pingpong.h"
  6.  
  7. #define APPNAME "PingPong"
  8.  
  9. IDirectDraw *lpDD=NULL;                    // DirectDrawオブジェクト
  10. IDirectDrawSurface *lpDDPrimary=NULL;    // プライマリサーフェス
  11. IDirectDrawSurface *lpDDBack=NULL;        // バックサーフェス
  12. IDirectDrawSurface *lpDDPad=NULL;        // オフスクリーンサーフェイス
  13. IDirectDrawSurface *lpDDBall=NULL;        //            "
  14. IDirectDrawSurface *lpDDBG=NULL;        //            "
  15.  
  16. HINSTANCE hAppInst;
  17. LRESULT CALLBACK WndProc(HWND, UINT, UINT, LONG);
  18.  
  19. BOOL bActive = FALSE;
  20. DWORD lastCount;
  21. // ボール
  22. struct ball{
  23.     float X,Y;         // 座標
  24.     float XAdd,YAdd; // 移動量
  25. }Ball;
  26. // パドル
  27. struct pad{
  28.     int X;         // 描画座標
  29.     int XAdd;     // 移動量
  30. }Pad;
  31. // 反発力テーブル
  32. float PadDir[16][2]={
  33.         -1.99036944f,-0.19603428f,    //左
  34.         -1.71388071f,-0.92603428f,    
  35.         -1.71388071f,-0.98056933f,    
  36.         -1.76384258f,-0.94279349f,    
  37.         -1.54602087f,-1.26878655f,    
  38.         -1.26878655f,-1.54602087f,    
  39.         -0.94279349f,-1.76384258f,    
  40.         -0.58056933f,-1.91388071f,    //中央
  41.         -0.19603428f,-1.99036944f,    //
  42.          0.19603428f,-1.99036944f,    
  43.          0.58056933f,-1.91388071f,    
  44.          0.94279349f,-1.76384258f,    
  45.          1.26878655f,-1.54602087f,    
  46.          1.54602087f,-1.26878655f,    
  47.          1.76384258f,-0.94279349f,    
  48.          1.71388071f,-0.98056933f,    //右
  49. };
  50.  
  51. int APIENTRY WinMain(HINSTANCE hInstance,
  52.                      HINSTANCE hPrevInstance,
  53.                      LPSTR     lpCmdLine,
  54.                      int       nCmdShow)
  55. {
  56.      WNDCLASS wc;
  57.     HWND hWnd;
  58.     MSG msg;
  59.  
  60.     wc.style=CS_HREDRAW|CS_VREDRAW;
  61.     wc.lpfnWndProc=WndProc;
  62.     wc.cbClsExtra=0;
  63.     wc.cbWndExtra=0;
  64.     wc.hInstance=hInstance;
  65.     wc.hIcon=LoadIcon(hInstance, IDI_APPLICATION);
  66.     wc.hCursor=LoadCursor(NULL, IDC_ARROW);
  67.     wc.hbrBackground=(HBRUSH)GetStockBrush(BLACK_BRUSH);
  68.     wc.lpszMenuName=0;
  69.     wc.lpszClassName=APPNAME;
  70.  
  71.     RegisterClass(&wc);
  72.     
  73.     hAppInst=hInstance;
  74.     // ウィンドウクラスの登録
  75.     hWnd=CreateWindowEx(0, APPNAME, APPNAME, WS_POPUP, 0, 0,
  76.         GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
  77.         NULL, NULL, hInstance, NULL);
  78.  
  79.     if(!hWnd) return FALSE;
  80.     
  81.     ShowWindow(hWnd, nCmdShow);
  82.     UpdateWindow(hWnd);
  83.  
  84.     // アプリケーションの初期化
  85.     if(!InitDDraw(hWnd)) return FALSE;
  86.     
  87.     // 初期化終了
  88.     bActive = TRUE;
  89.  
  90.     // メッセージポンプ
  91.     while(TRUE){
  92.         if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)){
  93.             if(!GetMessage(&msg, NULL, 0, 0)){
  94.                 return msg.wParam;
  95.             }
  96.             TranslateMessage(&msg);
  97.             DispatchMessage(&msg);
  98.         }
  99.         if(bActive)    Render();
  100.     }
  101.     return 0;
  102. }
  103.  
  104. long FAR PASCAL WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  105. {
  106.     switch(message){
  107.  
  108.     case WM_ACTIVATEAPP:
  109.         bActive=(BOOL)wParam;
  110.         if(bActive && lpDD)
  111.             ResumeScreen();
  112.         break;
  113.     case WM_CREATE:
  114.         break;
  115.     case WM_SETCURSOR:
  116.         SetCursor(NULL);
  117.         return TRUE;
  118.  
  119.     case WM_KEYDOWN:
  120.         switch(wParam){
  121.         case VK_ESCAPE:
  122.             DestroyWindow(hWnd);
  123.             break;
  124.         }
  125.         return TRUE;
  126.  
  127.     case WM_DESTROY:
  128.         bActive=FALSE;
  129.         ReleaseObjects();
  130.         PostQuitMessage(0);
  131.         break;
  132.     }
  133.     return DefWindowProc(hWnd,message,wParam,lParam);
  134. }
  135.  
  136. // オブジェクトの開放
  137. void ReleaseObjects()
  138. {
  139.     RELEASE(lpDDBG);
  140.     RELEASE(lpDDBall);
  141.     RELEASE(lpDDPad);
  142.     RELEASE(lpDDBack);
  143.     RELEASE(lpDDPrimary);
  144.     RELEASE(lpDD);
  145. }
  146.  
  147. // DirectDraw初期化エラー処理
  148. BOOL InitDDError(HWND hWnd)
  149. {
  150.     ReleaseObjects();
  151.     MessageBox(hWnd, "Initialize Error", "DirectDraw Initialize", MB_OK|MB_ICONHAND);
  152.     return FALSE;
  153. }
  154.  
  155. // サーフェスの修復
  156. BOOL ResumeScreen()
  157. {
  158.     DDCOLORKEY ddck;
  159.  
  160.     lpDDPrimary->Restore();
  161.     lpDDBack->Restore();
  162.     lpDDPad->Restore();
  163.     lpDDBall->Restore();
  164.     lpDDBG->Restore();
  165.  
  166.     HDC hDCDest;
  167.     lpDDPad->GetDC(&hDCDest);    // スプライトサーフェスのDCを取得
  168.     // リソースからビットマップをロード
  169.     HBITMAP hBmp=(HBITMAP)LoadImage(NULL, "Pad.Bmp", IMAGE_BITMAP,0, 0,
  170.         LR_LOADFROMFILE|LR_CREATEDIBSECTION);
  171.     HDC hDCSrc=CreateCompatibleDC(NULL);    // メモリデバイスコンテキストを作成
  172.  
  173.     // スプライトサーフェスへコピーする
  174.     SelectObject(hDCSrc, hBmp);    // ビットマップを選択
  175.     BitBlt(hDCDest, 0, 0, 64, 16, hDCSrc, 0, 0, SRCCOPY); // コピー
  176.     DeleteObject(hBmp);                    // ビットマップを復帰
  177.     lpDDPad->ReleaseDC(hDCDest);        // スプライトサーフェスのDCを開放
  178.     
  179.     lpDDBall->GetDC(&hDCDest);
  180.     hBmp=(HBITMAP)LoadImage(NULL, "Ball.Bmp", IMAGE_BITMAP,0, 0,
  181.         LR_LOADFROMFILE|LR_CREATEDIBSECTION );
  182.     SelectObject(hDCSrc, hBmp);
  183.     BitBlt(hDCDest, 0, 0, 16, 16, hDCSrc, 0, 0, SRCCOPY);
  184.     DeleteObject(hBmp);
  185.     lpDDBall->ReleaseDC(hDCDest);
  186.  
  187.     lpDDBG->GetDC(&hDCDest);
  188.     hBmp=(HBITMAP)LoadImage( NULL, "BG.Bmp", IMAGE_BITMAP,0, 0,
  189.         LR_LOADFROMFILE|LR_CREATEDIBSECTION );
  190.     
  191.     SelectObject(hDCSrc, hBmp);
  192.     BitBlt(hDCDest, 0, 0, 640, 480, hDCSrc, 0, 0, SRCCOPY);
  193.     DeleteObject(hBmp);
  194.     lpDDBG->ReleaseDC(hDCDest);
  195.     
  196.     DeleteDC(hDCSrc);    // メモリデバイスコンテキストを開放
  197.  
  198.     // カラーキーを設定
  199.     ddck.dwColorSpaceLowValue  = 0; // 黒を指定
  200.     ddck.dwColorSpaceHighValue = 0;
  201.     lpDDPad->SetColorKey(DDCKEY_SRCBLT, &ddck); 
  202.     lpDDBall->SetColorKey(DDCKEY_SRCBLT, &ddck);
  203.  
  204.     return TRUE;
  205. }
  206.  
  207. void Render()
  208. {
  209.     int x;
  210.     RECT rect;
  211.     
  212.     rect.left=rect.top=0;
  213.     rect.right=640;
  214.     rect.bottom = 480;
  215.     // 背景の描画
  216.     lpDDBack->BltFast(0, 0, lpDDBG, &rect, DDBLTFAST_WAIT|DDBLTFAST_NOCOLORKEY);
  217.  
  218.     Pad.XAdd=0;
  219.  
  220.     // キー入力 
  221.     if(GetAsyncKeyState(VK_RIGHT))    Pad.XAdd=10;    
  222.     if(GetAsyncKeyState(VK_LEFT))    Pad.XAdd=-10;
  223.         
  224.     if(Pad.X>525-42) Pad.X=525-42;
  225.     if(Pad.X<95) Pad.X=95;
  226.     
  227.     rect.right=64;
  228.     rect.bottom=16;
  229.     // パドルの描画
  230.     lpDDBack->BltFast(Pad.X, 416, lpDDPad,&rect,
  231.         DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY);
  232.     
  233.     Pad.X+=Pad.XAdd;    // パドルの移動
  234.     
  235.     // パドルとボールの当り判定
  236.     if((int)Ball.Y>416-16 && (int)Ball.Y<416){
  237.         if((int)Ball.X>Pad.X-8 && (int)Ball.X<Pad.X+64-8){
  238.             // パドルのどこにボールが当たったのか?
  239.             x=((int)(Ball.X+8-Pad.X)>>2)&0x0f;
  240.             // 反発力テーブルを参照して,ボールの移動量を決定
  241.             Ball.XAdd=PadDir[x][0]*2;
  242.             Ball.YAdd=PadDir[x][1]*2;
  243.         }
  244.     }
  245.  
  246.     // ボールの移動&描画
  247.     Ball.X+=Ball.XAdd;
  248.     Ball.Y+=Ball.YAdd;    
  249.     rect.right=16;
  250.     rect.bottom = 16;
  251.     lpDDBack->BltFast((int)Ball.X, (int)Ball.Y, lpDDBall, &rect,
  252.         DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY);
  253.  
  254.     // ボールの移動範囲をチェック    
  255.     if(Ball.X<95){
  256.         Ball.X=100;
  257.         Ball.XAdd=-Ball.XAdd;
  258.     }
  259.     if(Ball.X>530){
  260.         Ball.X=530;
  261.         Ball.XAdd=-Ball.XAdd;
  262.     }
  263.     if(Ball.Y<0){
  264.         Ball.Y=0;
  265.         Ball.YAdd=-Ball.YAdd;
  266.     }
  267.     // ミスをしたか?
  268.     if(Ball.Y>480-32)
  269.         InitGame();
  270.  
  271.     // ゲームウェイト
  272.     DWORD thisCount;
  273.     do thisCount=GetTickCount();
  274.     while(thisCount-lastCount<1000/120);
  275.  
  276.     // フリッピング
  277.     lpDDPrimary->Flip(NULL,DDFLIP_WAIT);
  278.  
  279.     lastCount=thisCount;
  280. }
  281.  
  282. // DirectDrawの初期化
  283. BOOL InitDDraw(HWND hWnd)
  284. {
  285.     // DirectDrawオブジェクトの作成
  286.     if(DirectDrawCreate(NULL,&lpDD,NULL)!=DD_OK) return FALSE;
  287.  
  288.     // 協調レベルの設定
  289.     lpDD->SetCooperativeLevel(hWnd,
  290.         DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
  291.  
  292.     // 画面モードの設定
  293.     lpDD->SetDisplayMode(640, 480, 16);
  294.     
  295.     // プライマリサーフェイスの初期化
  296.     DDSURFACEDESC ddsd;
  297.     DDSCAPS ddscaps;
  298.  
  299.     ZeroMemory(&ddsd, sizeof(ddsd));
  300.     ZeroMemory(&ddscaps, sizeof(ddscaps));
  301.  
  302.     ddsd.dwSize=sizeof(ddsd);
  303.     ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
  304.     ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|
  305.         DDSCAPS_FLIP|DDSCAPS_COMPLEX;
  306.     ddsd.dwBackBufferCount=1;
  307.  
  308.     lpDD->CreateSurface(&ddsd, &lpDDPrimary, NULL);
  309.  
  310.     ddscaps.dwCaps=DDSCAPS_BACKBUFFER;
  311.     lpDDPrimary->GetAttachedSurface(&ddscaps, &lpDDBack);
  312.     
  313.     // オフスクリーンサーフェイスの初期化
  314.     ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;        
  315.     ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
  316.     ddsd.dwWidth=64;
  317.     ddsd.dwHeight=24;
  318.     lpDD->CreateSurface(&ddsd, &lpDDPad, NULL);
  319.     
  320.     ddsd.dwWidth=16;
  321.     ddsd.dwHeight=16;
  322.     lpDD->CreateSurface(&ddsd, &lpDDBall, NULL);
  323.  
  324.     ddsd.dwWidth=640;
  325.     ddsd.dwHeight=480;
  326.     lpDD->CreateSurface(&ddsd, &lpDDBG, NULL);
  327.     
  328.     // プライマリとバックサーフェイスのクリア
  329.     DDBLTFX ddbltfx;
  330.     ZeroMemory(&ddbltfx, sizeof(DDBLTFX));
  331.     ddbltfx.dwSize=sizeof(DDBLTFX);
  332.     lpDDPrimary->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
  333.     lpDDBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
  334.  
  335.     if(!ResumeScreen()){
  336.         ReleaseObjects();
  337.         MessageBox(hWnd, "Surface Restore Error", "Surface Initialize", MB_OK|MB_ICONHAND);
  338.         return FALSE;
  339.     }
  340.     InitGame();
  341.  
  342.     return TRUE;
  343. }
  344. // ゲーム初期化
  345. void InitGame()
  346. {
  347.     // ゲーム情報の初期化
  348.     Pad.X=290;
  349.     Ball.X=Ball.Y=50;
  350.     Ball.XAdd=Ball.YAdd=2;
  351. }
  352.