#include <windows.h>
#include <ddraw.h>

#include <stdlib.h>
#include <stdio.h>
#include <time.h>


///////////
//定数定義//
///////////

#define DISPXSIZE       320             // 画面横サイズ 
#define DISPYSIZE       240             // 画面縦サイズ 
#define SPRITEXSIZE     320             // スプライト横サイズ 
#define SPRITEYSIZE     240             // スプライト縦サイズ 

///////////
//変数定義//
///////////

HWND hWND;                          // ウインドウハンドル 
HINSTANCE hINSTANCE;                // ウインドウインスタンス 
char lpszAppName[] = "DDsimple";	    // アプリケーション名 
int	spx,spy;						// スプライトの座標


//////////////////////
// DirectDraw構造体 //
//////////////////////

LPDIRECTDRAW            lpDD = NULL;            // DirectDrawオブジェクト
LPDIRECTDRAWSURFACE     lpFRONTSURFACE = NULL;  // プライマリサーフェス
LPDIRECTDRAWSURFACE     lpBACKSURFACE = NULL;   // バックサーフェス
LPDIRECTDRAWSURFACE     lpSPRITE = NULL;        // スプライトサーフェス
LPDIRECTDRAWPALETTE     lpPALETTE = NULL;       // パレット

PALETTEENTRY            pePAL[256];             // パレット構造体


/*===============
     関数定義
================*/
BOOL InitDDraw(HWND hwnd, int x, int y, int sx, int sy);
void ReleaseDDraw(void);
BOOL SetDDrawSprite(LPCSTR Resource , int sx , int sy);
void DrawDDrawSprite(int x, int y, RECT* rect);
void DrawDDrawSpriteClip(int x, int y, RECT* rect);
//void ResumeDDraw(void);

HRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    switch(iMsg){
        case WM_KEYDOWN: // キーが押された

            switch(wParam){
                case VK_ESCAPE: // 終了処理
					DestroyWindow(hWnd);
                    break;
                case VK_LEFT: // 左移動
						spx -= 8;break;
                case VK_RIGHT: // 右移動
						spx += 8;break;
                case VK_UP: // 上移動
						spy -= 8;break;
                case VK_DOWN: // 下移動
						spy += 8;break;
            }
            return(TRUE);
        case WM_ACTIVATEAPP:// 制御がこのアプリケーションに移った
            if((wParam) && (lpDD != NULL))
							// lpDDがNULLの時はResumeしてはいけない
			{	
                //ResumeDDraw(); // DirectDrawの再構築
                return(TRUE);
            }
            break;

        case WM_CLOSE: // ウインドウが閉じられた
			DestroyWindow(hWnd);
            return(TRUE);
        case WM_DESTROY: // ウインドウが破壊された
			ReleaseDDraw();
            PostQuitMessage(0);
            return(TRUE);
    }
    return(DefWindowProc(hWnd, iMsg, wParam, lParam));
}

int PASCAL WinMain(HINSTANCE hInstance,
					HINSTANCE hPrevInstance,
					LPSTR lpCmdLine,
					int nCmdShow)
{
    WNDCLASS wndclass;
	MSG msg;
    hINSTANCE = hInstance;

	////////////////////////////////////////
	// おきまりのウインドウクラス生成処理 //
	////////////////////////////////////////

    // ウインドウクラスの生成
    wndclass.style         = NULL;
    wndclass.lpfnWndProc   = WndProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance     = hINSTANCE;
    wndclass.hIcon         = LoadIcon(NULL,"ICON");
    wndclass.hCursor       = NULL;
    wndclass.hbrBackground = (HBRUSH )GetStockObject(BLACK_BRUSH);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = lpszAppName;
    RegisterClass(&wndclass);

    // ウインドウの生成
    hWND = CreateWindow(lpszAppName, lpszAppName,
                        WS_POPUP|WS_VISIBLE|WS_SYSMENU,
                        0, 0, 
                        GetSystemMetrics(SM_CXSCREEN),
                        GetSystemMetrics(SM_CYSCREEN),
                        NULL, NULL, hINSTANCE, NULL );


	////////////////////////
	// 本格的な初期化処理 //
	////////////////////////



	// DirectDrawとその他初期化
    if(InitDDraw(hWND, DISPXSIZE, DISPYSIZE, SPRITEXSIZE , SPRITEYSIZE) != TRUE)
	{
		MessageBox(hWND,"Can't create DirectDraw Object",
						"error",MB_APPLMODAL);
        DestroyWindow(hWND);    
    } 
	else
	{
		
        for(;;){ // メインループ
			while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
					{
	 	    	if (msg.message == WM_QUIT)
						{                               
						PostQuitMessage(msg.wParam);
						return 0;
						}
    				TranslateMessage(&msg);
        			DispatchMessage(&msg);
					}

			// 画面クリア
		    DDBLTFX ddbltfx;
			ZeroMemory(&ddbltfx, sizeof(DDBLTFX));
			ddbltfx.dwSize = sizeof(DDBLTFX);
			lpBACKSURFACE->Blt(NULL, NULL, NULL,DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);

        }
    }


 

	   return(FALSE);
}


BOOL InitDDraw(HWND hwnd, int x, int y, int sx, int sy)
{
    DDSURFACEDESC   ddsd;	// DirectDrawサーフェスの属性情報を格納する
    DDSCAPS         ddscaps;	// DirectDrawサーフェスの能力情報を格納する

    // DirectDrawオブジェクトを生成    
    if(  DirectDrawCreate( NULL , &lpDD , NULL ) != DD_OK )return FALSE;//失敗
	
	// DirectDraw協調レベルを設定
    lpDD->SetCooperativeLevel(  hwnd , DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN |
									   DDSCL_ALLOWMODEX);
				// DDSCL_EXCLUSIVE  排他モード(占有モード)
				// DDSCL_FULLSCREEN フルスクリーンモード
				// DDSCL_ALLOWMODEX ModeXモード
    lpDD->SetDisplayMode(x, y, 8); // 256色

    // プラリマリサーフェスの初期化
    ZeroMemory(&ddsd, sizeof( ddsd ) );//	ゼロクリア
    ddsd.dwSize = sizeof( ddsd );		//	サイズ格納
    ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;	// 有効データ指定フラグ設定
				// DDSD_CAPS ddsCapsを有効化
				// DDSD_BACKBUFFERCOUNT dwBackBufferCountを有効化
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;
				// DDSCAPS_PRIMARYSURFACE プライマリサーフェスであることを明示
				// DDSCAPS_FLIP フリップを可能にする
				// DDSCAPS_COMPLEX 複合サーフェスの使用を指定
    ddsd.dwBackBufferCount = 1;
				// バックバッファの数を指定(この場合、バックサーフェスのみな
				// ので1を指定している。
	
    lpDD->CreateSurface( &ddsd , &lpFRONTSURFACE , NULL);
				//ddsdの設定に基づいてサーフェスを作成。サーフェスオブジェクト
				//はlpFRONTSURFACEから参照可能

    // バックサーフェスの初期化
    ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
				//DDCAPS_BACKBUFFER バックバッファであることを指定
    lpFRONTSURFACE->GetAttachedSurface( &ddscaps , &lpBACKSURFACE);
			// ddscapsの指定に基づいてアタッチドサーフェス(バックサーフェス)
			// を生成。オブジェクトはlpBACKSURFACEから参照可能。

    // パレットの生成
    lpDD->CreatePalette( DDPCAPS_8BIT , pePAL , &lpPALETTE , NULL); 
													// 8ビット(256色)
    lpFRONTSURFACE->SetPalette( lpPALETTE );
										 // フロントサーフェスにパレットを設定


    // スプライトサーフェスの生成
    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH|DDSD_HEIGHT;
		// DDSD_CAPS ddsCapsを有効化
		// DDSD_WIDTH dwWidthを有効化
		// DDSD_HEIGHT dwHeightを有効化
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
		// DDSCAPS_OFFSCREENPLAIN 非表示画面属性を設定
    ddsd.dwWidth = sx;	// スプライトサーフェス横幅
    ddsd.dwHeight = sy;	// スプライトサーフェス縦幅
    lpDD->CreateSurface( &ddsd , &lpSPRITE , NULL);// スプライトサーフェス生成

    return(TRUE);//成功
}

#if 0
////////////////////////////////////////////////////////////////////

	DirectDrawの終了処理(){}

	void ReleaseDDraw(void)


	各々のDirectDraw資源を開放する

////////////////////////////////////////////////////////////////////
#endif 
void ReleaseDDraw(void)
{
    if( lpSPRITE       != NULL) lpSPRITE->Release();
    if( lpPALETTE      != NULL) lpPALETTE->Release();
    if( lpFRONTSURFACE != NULL) lpFRONTSURFACE->Release();
    if( lpDD           != NULL) lpDD->Release();
}