#include #include #include #include #define FLIP_BLANK (1000/60) #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 #define COLOR_KEY 2 int screen_width, screen_height; char key_map[256]; DWORD wait_time; HWND g_hWnd = NULL; LPDIRECTDRAW lpDD = NULL; LPDIRECTDRAWSURFACE lpFront = NULL; LPDIRECTDRAWSURFACE lpBack = NULL; LPDIRECTDRAWSURFACE lpWork = NULL; PALETTEENTRY peEntry[256]; LPDIRECTDRAWPALETTE lpPalette = NULL; /* * DirectDraw */ int initDD(HWND hWnd, int w, int h, int ck){ DDSURFACEDESC ddsd; DDSCAPS ddscaps; DDCOLORKEY ddck = {ck, ck}; screen_width = w; screen_height = h; if(DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK){ return 0; } if(lpDD->SetCooperativeLevel(hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE) != DD_OK){ return 0; } if(lpDD->SetDisplayMode(w, h, 8) != DD_OK){ return 0; } ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 1; if(lpDD->CreateSurface(&ddsd, &lpFront, NULL) != DD_OK){ return 0; } ddscaps.dwCaps = DDSCAPS_BACKBUFFER; if(lpFront->GetAttachedSurface(&ddscaps, &lpBack) != DD_OK){ return 0; } ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; // | DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = w; ddsd.dwHeight = h; if((lpDD->CreateSurface(&ddsd, &lpWork, NULL)) != DD_OK){ return 0; } if(lpDD->CreatePalette(DDPCAPS_8BIT, peEntry, &lpPalette, NULL) != DD_OK){ return 0; } lpFront->SetPalette(lpPalette); lpWork->SetColorKey(DDCKEY_SRCBLT, &ddck); peEntry[1].peRed = 255; peEntry[1].peGreen = 0; peEntry[1].peBlue = 0; peEntry[1].peFlags = 1; lpPalette->SetEntries(0, 1, 1, &peEntry[1]); return 1; } #define RELEASE(i) if(i){i->Release();i=NULL;} void deinitDD(void){ RELEASE(lpPalette); RELEASE(lpFront); lpBack = NULL; RELEASE(lpWork); RELEASE(lpDD); } void fillBackSurface(unsigned char c){ DDBLTFX ddbltfx; ZeroMemory(&ddbltfx, sizeof(DDBLTFX)); ddbltfx.dwSize=sizeof(DDBLTFX); ddbltfx.dwFillColor = c; lpBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); } void drawPoint(LPDIRECTDRAWSURFACE lpsf, int x, int y, int c){ unsigned char *p; DDSURFACEDESC desc; ZeroMemory(&desc, sizeof(DDSURFACEDESC)); desc.dwSize = sizeof(DDSURFACEDESC); lpsf->Lock(NULL, &desc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); p = (unsigned char *)desc.lpSurface; p[x + y * desc.lPitch] = c; lpsf->Unlock(desc.lpSurface); } HRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ switch(message){ case WM_KEYDOWN: if(wParam == VK_ESCAPE){ PostMessage(hWnd, WM_CLOSE, 0, 0); return 0; } key_map[wParam] = 1; return 0; case WM_KEYUP: key_map[wParam] = 0; return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR, int nCmdShow){ MSG msg; WNDCLASS wc; int cx = 0; int cy = 0; DWORD color_key[2] = {DDBLTFAST_NOCOLORKEY, DDBLTFAST_SRCCOLORKEY}; if(!hPrevInst){ wc.lpszClassName = "DirectDraw"; wc.lpfnWndProc = WndProc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.hInstance = hInst; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.cbClsExtra = 0; wc.cbWndExtra = 0; if(RegisterClass(&wc) == 0){ return 0; } } HWND hWnd = CreateWindow( "DirectDraw", "DirectDraw Test", WS_POPUPWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInst, NULL); if(hWnd == NULL){ return 0; } g_hWnd = hWnd; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); if(!(initDD(hWnd, SCREEN_WIDTH, SCREEN_HEIGHT, COLOR_KEY))){ return 0; } RECT rect = {0, 0, 64, 64}; for(int i = 0; i < 64 * 64; i++){ int x = i % 64; int y = i / 64; // ロックとアンロックを繰り返すので本当は良くない if(x < 4 || x >= 60 || y < 4 || y >= 60){ drawPoint(lpWork, x, y, 1); } else{ drawPoint(lpWork, x, y, COLOR_KEY); } } // カーソル非表示 ShowCursor(FALSE); // IMEバーを非表示 WINNLSEnableIME(NULL, FALSE); while(1){ wait_time = timeGetTime(); fillBackSurface(255); if(key_map[VK_UP]){ cy -= 3; } else if(key_map[VK_DOWN]){ cy += 1; } if(key_map[VK_LEFT]){ cx -= 4; } else if(key_map[VK_RIGHT]){ cx += 2; } if(cx < 0)cx = 0; if(cy < 0)cy = 0; lpBack->BltFast(cx, cy, lpWork, &rect, color_key[1] | DDBLTFAST_WAIT); lpFront->Flip(NULL, DDFLIP_WAIT); do{ while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ if(msg.message == WM_QUIT){ goto fin; } TranslateMessage(&msg); DispatchMessage(&msg); } }while(timeGetTime() < wait_time + FLIP_BLANK); } fin: deinitDD(); ShowCursor(TRUE); return msg.wParam; }