#include #include #include #define EXT /* */ class nmDDraw; class nmDDSurf; #define ON_VRAM 0 #define ON_SYSTEMMEMORY 1 #define RELEASE(x) if(x){x->Release();x=NULL;} //DirectDraw用自作クラス class nmDDraw{ public: nmDDraw(); ~nmDDraw(); int initDD(HWND hWnd, HINSTANCE hInst, int wx, int wy, int bit); void deinitDD(HWND hWnd); void setPalColor(int index, int r, int g, int b); void clearBackSurf(int num); void bltSurf(int px, int py, nmDDSurf *pNmDDsurf, int x, int y, int wx, int wy); void flipSurf(); void restoreSurf(); LPDIRECTDRAW getDDraw(); LPDIRECTDRAWSURFACE getFrontSurf(); LPDIRECTDRAWSURFACE getBackSurf(); protected: int width, height, bit; HINSTANCE hInst; LPDIRECTDRAW pDDraw; LPDIRECTDRAWSURFACE pDDFrontSurf; LPDIRECTDRAWSURFACE pDDBackSurf; PALETTEENTRY peEntry[256]; LPDIRECTDRAWPALETTE pDDPallet; }; //DirectDraw用自作ワークサーフェスクラス class nmDDSurf{ public: nmDDSurf(); ~nmDDSurf(); int initDDSurf(nmDDraw *pDDraw, int wx, int wy, int flag); void deinitDDSurf(); void setColorKey(int n1, int n2); void drawBMP(int x, int y, int wx, int wy, int *c); LPDIRECTDRAWSURFACE getWorkSurf(); protected: int width, height; LPDIRECTDRAWSURFACE pDDWorkSurf; }; ////////////////////////////// // ここから nmDDraw // nmDDraw::nmDDraw(){ pDDraw = NULL; pDDFrontSurf = NULL; pDDBackSurf = NULL; pDDPallet = NULL; } nmDDraw::~nmDDraw(){ //nothing to do } // DirectDrawの初期化 画面の解像度 横幅、縦幅、ビット(8 or 16 or 32) を設定 int nmDDraw::initDD(HWND hWnd, HINSTANCE hInst, int wx, int wy, int bit) { DDSURFACEDESC ddsd; DDSCAPS ddscaps; if(DirectDrawCreate(NULL, &pDDraw, NULL) != DD_OK){ return 0; } if(pDDraw->SetCooperativeLevel(hWnd, DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ) != DD_OK){ return 0; } if(pDDraw->SetDisplayMode(wx, wy, bit) != 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(pDDraw->CreateSurface(&ddsd, &pDDFrontSurf, NULL) != DD_OK){ return 0; } // バックサーフェスを作成 ZeroMemory(&ddscaps, sizeof(ddscaps)); ddscaps.dwCaps = DDSCAPS_BACKBUFFER; if(pDDFrontSurf->GetAttachedSurface(&ddscaps, &pDDBackSurf) != DD_OK){ return 0; } if(bit == 8){ if(pDDraw->CreatePalette(DDPCAPS_8BIT, peEntry, &pDDPallet, NULL) != DD_OK){ return 0; } pDDFrontSurf->SetPalette(pDDPallet); } this->hInst = hInst; this->width = wx; this->height = wy; this->bit = bit; return 1; } // DirectDrawの解放 void nmDDraw::deinitDD(HWND hWnd) { RELEASE(pDDPallet); RELEASE(pDDFrontSurf); pDDBackSurf = NULL; pDDraw->RestoreDisplayMode(); pDDraw->SetCooperativeLevel(hWnd , DDSCL_NORMAL | DDSCL_ALLOWREBOOT); RELEASE(pDDraw); } void nmDDraw::setPalColor(int index, int r, int g, int b){ if(pDDPallet == NULL){ return; } peEntry[index].peRed = r; peEntry[index].peGreen = g; peEntry[index].peBlue = b; peEntry[index].peFlags = 1; pDDPallet->SetEntries(0, index, 1, &peEntry[index]); } void nmDDraw::clearBackSurf(int num){ DDBLTFX DDBltfx; // DDBLTFX構造体の設定 ZeroMemory(&DDBltfx ,sizeof(DDBltfx)); DDBltfx.dwSize = sizeof(DDBltfx); DDBltfx.dwDDFX = DDBLTFX_NOTEARING; DDBltfx.dwFillColor = num; pDDBackSurf->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &DDBltfx); } void nmDDraw::bltSurf(int px, int py, nmDDSurf *pNmDDSurf, int x, int y, int wx, int wy){ RECT rect; int udx = width - px; int udy = height - py; LPDIRECTDRAWSURFACE pDDWorkSurf = pNmDDSurf->getWorkSurf(); if((udx <= 0) || (udy <= 0))return; if(px < 0){ if(px + wx <= 0)return; x -= px; wx += px; px = 0; } if(py < 0){ if(py + wy <= 0)return; y -= py; wy += py; py = 0; } if(wx - udx > 0){ wx = udx; } if(wy - udy > 0){ wy = udy; } rect.left = x; rect.right = x + wx; rect.top = y; rect.bottom = y + wy; pDDBackSurf->BltFast(px, py, pDDWorkSurf, &rect, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); } void nmDDraw::flipSurf(){ pDDFrontSurf->Flip(NULL, DDFLIP_WAIT); } // サーフェスのリストア void nmDDraw::restoreSurf() { if(pDDFrontSurf->IsLost() == DDERR_SURFACELOST) pDDFrontSurf->Restore(); if(pDDBackSurf->IsLost() == DDERR_SURFACELOST) pDDBackSurf->Restore(); } // DirectDrawのポインタを返す LPDIRECTDRAW nmDDraw::getDDraw(){ return pDDraw; } // プライマリサーフェスのポインタを返す LPDIRECTDRAWSURFACE nmDDraw::getFrontSurf(){ return pDDFrontSurf; } // バックサーフェスのポインタを返す LPDIRECTDRAWSURFACE nmDDraw::getBackSurf(){ return pDDBackSurf; } // ここまで nmDDraw // ////////////////////////////// ////////////////////////////// // ここから nmDDSurf // nmDDSurf::nmDDSurf(){ pDDWorkSurf = NULL; } nmDDSurf::~nmDDSurf(){ //nothing to do } int nmDDSurf::initDDSurf(nmDDraw *pNmDDraw, int wx, int wy, int flag){ DDSURFACEDESC ddsd; int k[2] = {0, DDSCAPS_SYSTEMMEMORY}; LPDIRECTDRAW pDDraw = pNmDDraw->getDDraw(); ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | k[flag]; ddsd.dwWidth = wx; ddsd.dwHeight = wy; if((pDDraw->CreateSurface(&ddsd, &pDDWorkSurf, NULL)) != DD_OK){ return 0; } this->width = wx; this->height = wy; return 1; } void nmDDSurf::deinitDDSurf(){ RELEASE(pDDWorkSurf); } void nmDDSurf::setColorKey(int n1, int n2){ DDCOLORKEY ddck = {n1, n2}; pDDWorkSurf->SetColorKey(DDCKEY_SRCBLT, &ddck); } void nmDDSurf::drawBMP(int x, int y, int wx, int wy, int *c){ int s = 0; int i, t, t2; int size_y = y + wy; int size_x = x + wx; unsigned char *p; DDSURFACEDESC desc; ZeroMemory(&desc, sizeof(DDSURFACEDESC)); desc.dwSize = sizeof(DDSURFACEDESC); pDDWorkSurf->Lock(NULL, &desc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); p = (unsigned char *)desc.lpSurface; for(t = y; t < size_y; t++){ t2 = t * desc.lPitch; for(i = x; i < size_x; i++, s++){ p[i + t2] = c[s]; } } pDDWorkSurf->Unlock(desc.lpSurface); } // ワークサーフェスのポインタを返す LPDIRECTDRAWSURFACE nmDDSurf::getWorkSurf(){ return pDDWorkSurf; } // ここまで nmDDSurf // ////////////////////////////// #include #define WINDOW_CLASS_NAME "DirectDrawTest" #define WINDOW_CAPTION "DirectDrawTest" #define DD_FPS 15 #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 LPDIRECTDRAWSURFACE7 pFrontSurf = NULL; LPDIRECTDRAWSURFACE7 pBackSurf = NULL; nmDDraw nmdd; nmDDSurf *pWorkSurf[1] = {NULL}; char key_map[256]; LRESULT WINAPI WndProc(HWND, UINT, WPARAM, LPARAM); //ウィンドウプロシージャ LRESULT WINAPI WndProc(HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam) { switch(message) { // 何かキーが押されたとき case WM_KEYDOWN: switch(wParam){ case 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){ int i; int result; DWORD wait_time; MSG msg; WNDCLASS wc; if(!hPrevInst){ wc.lpszClassName = WINDOW_CLASS_NAME; 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( WINDOW_CLASS_NAME, WINDOW_CAPTION, WS_POPUPWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInst, NULL); if(hWnd == NULL){ return 0; } // 初期化処理 result = nmdd.initDD(hWnd, hInst, SCREEN_WIDTH, SCREEN_HEIGHT, 8); if(result == 0){ return 0; } nmdd.setPalColor(1, 255, 0, 0); pWorkSurf[0] = new nmDDSurf(); pWorkSurf[0]->initDDSurf(&nmdd, 4, 4, ON_SYSTEMMEMORY); pWorkSurf[0]->setColorKey(255, 255); int pbuf[16] = {255, 1, 1, 255, 1, 255, 255, 1, 1, 255, 255, 1, 255, 1, 1, 255}; pWorkSurf[0]->drawBMP(0, 0, 4, 4, pbuf); ShowCursor(FALSE); WINNLSEnableIME(NULL, FALSE); // メインループ while(1){ wait_time = timeGetTime(); nmdd.clearBackSurf(255); for(i = 0; i < 1024; i++){ nmdd.bltSurf(rand() % (SCREEN_WIDTH + 4) - 4, rand() % (SCREEN_WIDTH + 4) - 4, pWorkSurf[0], 0, 0, 4, 4); } nmdd.flipSurf(); do{ while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ if(msg.message == WM_QUIT){ goto fin; } TranslateMessage(&msg); DispatchMessage(&msg); } }while(timeGetTime() < wait_time + 1000 / DD_FPS); } fin: ShowCursor(TRUE); pWorkSurf[0]->deinitDDSurf(); nmdd.deinitDD(hWnd); Sleep(1000); return msg.wParam; }