/*       RPG製作記2 1999/ 4/ 6 宍戸 輝光 */ #include #include #include LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); void none(void); void scroll(void); void wait(void); void makeBG(int,int); void event(int); void message(LPCTSTR); LPDIRECTDRAW lpDD=NULL; LPDIRECTDRAWSURFACE lpDDSPrimary=NULL,lpDDSBack=NULL,lpDDSMap=NULL; LPDIRECTDRAWSURFACE lpDDSScreen=NULL,lpDDSParts[3],lpDDSChr=NULL,lpDDSMessage=NULL; DDSURFACEDESC ddsdpr,ddsdbb,ddsdmap,ddsdsc,ddsdpt[3],ddsdch,ddsdms; DDSCAPS ddscaps; LPDIRECTDRAWPALETTE lpDPalette; RECT recScreen={0,0,800,600},recChr={0,0,32,32},recMes={0,0,384,192}; RECT recMText={8,8,376,184}; int iX,iY,iDx,iDy,iDdx,iDdy,iScd=2,iState; BYTE map[64][64]; WORD mInfo[64][64]; DWORD dwTime; BOOL fSc; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ MSG msg; WNDCLASSEX wndclass ; PALETTEENTRY pePal[256]; int i,j; LPBYTE lpBuf; wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "CWindow"; wndclass.hIconSm = NULL; RegisterClassEx (&wndclass); HWND hwnd=CreateWindowEx(WS_EX_TOPMOST,"CWindow",NULL, WS_POPUP,0,0,800,600,NULL,NULL,hInstance,NULL); ShowWindow (hwnd,iCmdShow); // ウインドウを表示 UpdateWindow (hwnd); DirectDrawCreate(NULL,&lpDD,NULL); // DirectDrawオブジェクト作成 lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); lpDD->SetDisplayMode(800,600,8); // 画面を640*480/8Bit モードに設定 FillMemory(&ddsdpr,0,sizeof(ddsdpr)); // プライマリサーフェス作成 ddsdpr.dwSize=sizeof(ddsdpr); ddsdpr.dwFlags=DDSD_CAPS| DDSD_BACKBUFFERCOUNT; ddsdpr.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX; ddsdpr.dwBackBufferCount = 1; lpDD->CreateSurface(&ddsdpr,&lpDDSPrimary,NULL); pePal[1].peRed=32; pePal[1].peGreen=0; pePal[1].peBlue=240; pePal[1].peFlags=NULL; pePal[2].peRed=64; pePal[2].peGreen=96; pePal[2].peBlue=255; pePal[2].peFlags=NULL; pePal[3].peRed=64; pePal[3].peGreen=240; pePal[3].peBlue=0; pePal[3].peFlags=NULL; pePal[4].peRed=32; pePal[4].peGreen=192; pePal[4].peBlue=0; pePal[4].peFlags=NULL; pePal[5].peRed=224; pePal[5].peGreen=96; pePal[5].peBlue=64; pePal[5].peFlags=NULL; pePal[6].peRed=160; pePal[6].peGreen=160; pePal[6].peBlue=176; pePal[6].peFlags=NULL; pePal[7].peRed=144; pePal[7].peGreen=128; pePal[7].peBlue=128; pePal[7].peFlags=NULL; pePal[8].peRed=96; pePal[8].peGreen=116; pePal[8].peBlue=80; pePal[8].peFlags=NULL; pePal[255].peRed=255; pePal[255].peGreen=255; pePal[255].peBlue=255; pePal[255].peFlags=NULL; lpDD->CreatePalette(DDPCAPS_8BIT,pePal,&lpDPalette,NULL); lpDPalette->SetEntries(0,0,256,pePal); lpDDSPrimary->SetPalette(lpDPalette); // パレット設定 // バックバッファ取得 ddscaps.dwCaps = DDSCAPS_BACKBUFFER; lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBack); FillMemory(&ddsdmap,0,sizeof(ddsdmap)); // マップ用サーフェス作成 ddsdmap.dwSize=sizeof(ddsdmap); ddsdmap.dwFlags=DDSD_CAPS| DDSD_WIDTH| DDSD_HEIGHT; ddsdmap.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; ddsdmap.dwWidth=544; ddsdmap.dwHeight=544; lpDD->CreateSurface(&ddsdmap,&lpDDSMap,NULL); FillMemory(&ddsdsc,0,sizeof(ddsdsc)); // 背景用サーフェス作成 ddsdsc.dwSize=sizeof(ddsdsc); ddsdsc.dwFlags=DDSD_CAPS| DDSD_WIDTH| DDSD_HEIGHT; ddsdsc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; ddsdsc.dwWidth=800; ddsdsc.dwHeight=600; lpDD->CreateSurface(&ddsdsc,&lpDDSScreen,NULL); for (i=0;i<3;i++) { // マップパーツ用サーフェス作成 FillMemory(&ddsdpt[i],0,sizeof(ddsdpt[i])); ddsdpt[i].dwSize=sizeof(ddsdpt[i]); ddsdpt[i].dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT; ddsdpt[i].ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; ddsdpt[i].dwWidth=32; ddsdpt[i].dwHeight=32; lpDD->CreateSurface(&ddsdpt[i],&lpDDSParts[i],NULL); } FillMemory(&ddsdch,0,sizeof(ddsdch)); // 主人公用サーフェス作成 ddsdch.dwSize=sizeof(ddsdch); ddsdch.dwFlags=DDSD_CAPS| DDSD_WIDTH| DDSD_HEIGHT; ddsdch.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; ddsdch.dwWidth=32; ddsdch.dwHeight=32; lpDD->CreateSurface(&ddsdch,&lpDDSChr,NULL); DDCOLORKEY ddck; // 主人公サーフェスに透過色設定 ddck.dwColorSpaceLowValue=0; ddck.dwColorSpaceHighValue=0; lpDDSChr->SetColorKey(DDCKEY_SRCBLT,&ddck); // メッセージウインドウ用サーフェス作成 FillMemory(&ddsdms,0,sizeof(ddsdms)); ddsdms.dwSize=sizeof(ddsdms); ddsdms.dwFlags=DDSD_CAPS| DDSD_WIDTH| DDSD_HEIGHT; ddsdms.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; ddsdms.dwWidth=384; ddsdms.dwHeight=192; lpDD->CreateSurface(&ddsdms,&lpDDSMessage,NULL); srand((unsigned)time(NULL)); lpDDSScreen->Lock(NULL,&ddsdsc,DDLOCK_WAIT,NULL); lpBuf=(BYTE*)ddsdsc.lpSurface; FillMemory(lpBuf,800*600,8); for (i=56;i<600;i++) FillMemory(lpBuf+i*800,544,7); lpDDSScreen->Unlock(NULL); lpDDSParts[0]->Lock(NULL,&ddsdpt[0],DDLOCK_WAIT,NULL); lpBuf=(BYTE*)ddsdpt[0].lpSurface; FillMemory(lpBuf,32*32,1); for (i=0;i<64;i++) lpBuf[rand() % 32+(rand() % 32)*32]=2; lpDDSParts[0]->Unlock(NULL); lpDDSParts[1]->Lock(NULL,&ddsdpt[1],DDLOCK_WAIT,NULL); lpBuf=(BYTE*)ddsdpt[1].lpSurface; // オフスクリーンサーフェスのポインタ FillMemory(lpBuf,32*32,3); for (i=0;i<64;i++) lpBuf[rand() % 32+(rand() % 32)*32]=4; lpDDSParts[1]->Unlock(NULL); lpDDSParts[2]->Lock(NULL,&ddsdpt[2],DDLOCK_WAIT,NULL); lpBuf=(BYTE*)ddsdpt[2].lpSurface; // オフスクリーンサーフェスのポインタ FillMemory(lpBuf,32*32,3); for (i=0;i<64;i++) lpBuf[rand() % 32+(rand() % 32)*32]=4; for (i=2;i<10;i++) FillMemory(lpBuf+12+i*32,8,5); for (i=10;i<24;i++) FillMemory(lpBuf+10+i*32,12,8); lpDDSParts[2]->Unlock(NULL); lpDDSChr->Lock(NULL,&ddsdch,DDLOCK_WAIT,NULL); lpBuf=(BYTE*)ddsdch.lpSurface; // オフスクリーンサーフェスのポインタ FillMemory(lpBuf,32*32,0); for (i=2;i<10;i++) FillMemory(lpBuf+12+i*32,8,5); for (i=10;i<24;i++) FillMemory(lpBuf+10+i*32,12,6); lpDDSChr->Unlock(NULL); // マップと属性配列作成 for (i=0;i<64;i++) for (j=0;j<64;j++) if (i<8 || j<8 || j>55||i>55) { map[j][i]=0; mInfo[j][i]=0x0001; } else { if (rand() % 16==0) { map[j][i]=0; mInfo[j][i]=0x0001; } else { map[j][i]=1; mInfo[j][i]=0x8000; } } map[32][30]=2; mInfo[32][30]=0x0002; map[34][25]=2; mInfo[34][25]=0x0003; map[32][32]=1; iX=32; iY=32; iDx=0; iDy=0; iDdx=0; iDdy=0; iState=0; makeBG(iX,iY); lpDDSBack->BltFast(0,0,lpDDSScreen,&recScreen,DDBLTFAST_NOCOLORKEY); dwTime=GetTickCount(); while (1) { /* メインループ */ if (PeekMessage (&msg,NULL,0,0,PM_NOREMOVE)) { if (!GetMessage (&msg,NULL,0,0)) // メッセージ処理 return msg.wParam ; TranslateMessage(&msg); DispatchMessage(&msg); } else switch (iState) { case 0: // 通常時 none(); break; case 1: // スクロール中 scroll(); break; case 2: // リターンキー入力待ち wait(); break; } } } void scroll(void) { if (GetTickCount()>dwTime+5) dwTime=GetTickCount(); else return; RECT rec; iDx+=iDdx; iDy+=iDdy; rec.left=iDx; rec.top=iDy; rec.right=iDx+480; rec.bottom=iDy+480; // スクロール終了時の処理 if (!(iDx!=0 && iDy!=0 && iDx!=64 && iDy!=64)) { makeBG(iX,iY); iDx=0; iDy=0; iDdx=0; iDdy=0; iState=0; return; } // バックバッファにマップを描画 lpDDSBack->BltFast(32,88,lpDDSMap,&rec,DDBLTFAST_NOCOLORKEY); // バックバッファに主人公を描画(透過処理) lpDDSBack->BltFast(224+32,224+88,lpDDSChr,&recChr,DDBLTFAST_SRCCOLORKEY); // バックバッファをフリップ lpDDSPrimary->Flip(NULL,DDFLIP_WAIT); } void none(void) { // 通常時 int kX,kY; iDx=32; iDy=32; iDdy=0; iDdy=0; kX=0; kY=0; // カーソルキーで移動 if (GetAsyncKeyState(VK_UP)<0) { kY=-1; if(mInfo[iX][iY-1]>32767) { iY--; // 主人公の位置更新 iDdx=0; // スクロール方向設定 iDdy=-iScd; kY=0; iState=1; // スクロールフラグセット } } else if (GetAsyncKeyState(VK_RIGHT)<0) { kX=1; if(mInfo[iX+1][iY]>32767) { iX++; iDdx=iScd; iDdy=0; kX=0; iState=1; } } else if (GetAsyncKeyState(VK_DOWN)<0) { kY=1; if(mInfo[iX][iY+1]>32767) { iY++; iDdx=0; iDdy=iScd; kY=0; iState=1; } } else if (GetAsyncKeyState(VK_LEFT)<0) { kX=-1; if(mInfo[iX-1][iY]>32767) { iX--; iDdx=-iScd; iDdy=0; kX=0; iState=1; } } // イベント判定 if ((mInfo[iX+kX][iY+kY] & 0xff)!=0) event(mInfo[iX+kX][iY+kY] & 0xff); } void makeBG(int x,int y) { RECT rec={32,32,512,512}; int i,j; for (i=0;i<17;i++) for (j=0;j<17;j++) lpDDSMap->BltFast(j*32,i*32,lpDDSParts[map[j+x-8][i+y-8]], &recChr,DDBLTFAST_NOCOLORKEY); // バックバッファに背景を描画 lpDDSBack->BltFast(0,0,lpDDSScreen,&recScreen,DDBLTFAST_NOCOLORKEY); // バックバッファにマップを描画 lpDDSBack->BltFast(32,88,lpDDSMap,&rec,DDBLTFAST_NOCOLORKEY); // バックバッファに主人公を描画(透過処理) lpDDSBack->BltFast(224+32,224+88,lpDDSChr,&recChr,DDBLTFAST_SRCCOLORKEY); // バックバッファをフリップ lpDDSPrimary->Flip(NULL,DDFLIP_WAIT); } void event(int e) { switch (e) { case 1: message("水です。\n2行目"); break; case 2: message( "人物1\nテストテストテストテストテストテストテストテストテスト"); break; case 3: message("人物2"); break; } iState=2; // 入力待ち } void message(LPCTSTR str) { // メッセージ表示 RECT rec={32,32,512,512}; HDC hdc; // メッセージウインドウをクリア lpDDSMessage->Lock(NULL,&ddsdms,DDLOCK_WAIT,NULL); LPBYTE lpBuf=(BYTE*)ddsdms.lpSurface; // オフスクリーンサーフェスのポインタ FillMemory(lpBuf,384*192,255); for (int i=2;i<190;i++) FillMemory(lpBuf+2+i*384,380,0); lpDDSMessage->Unlock(NULL); // メッセージウインドウサーフェスのデバイスコンテキスト取得 lpDDSMessage->GetDC(&hdc); // メッセージ描画 SetTextColor(hdc,0x00ffffff); SetBkMode(hdc,TRANSPARENT); DrawText(hdc,str,-1,&recMText,DT_LEFT|DT_WORDBREAK); lpDDSMessage->ReleaseDC(hdc); // バックバッファに背景を描画 lpDDSBack->BltFast(0,0,lpDDSScreen,&recScreen,DDBLTFAST_NOCOLORKEY); // バックバッファにマップを描画 lpDDSBack->BltFast(32,88,lpDDSMap,&rec,DDBLTFAST_NOCOLORKEY); // バックバッファに主人公を描画(透過処理) lpDDSBack->BltFast(224+32,224+88,lpDDSChr,&recChr,DDBLTFAST_SRCCOLORKEY); lpDDSBack->BltFast(48+32,272+88,lpDDSMessage,&recMes,DDBLTFAST_NOCOLORKEY); // バックバッファをフリップ lpDDSPrimary->Flip(NULL,DDFLIP_WAIT); } void wait(void) { // 入力待ち if (GetAsyncKeyState(VK_RETURN)<0) { makeBG(iX,iY); iState=0; } } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { int i; switch (iMsg) { case WM_KEYDOWN: if (wParam==VK_ESCAPE) // エスケープキーが押されたら終了 PostMessage(hwnd,WM_CLOSE,0,0); break; case WM_DESTROY : // 終了処理 lpDD->RestoreDisplayMode(); // 画面モードを元に戻す for (i=0;i<2;i++) if (lpDDSParts[i]) // パーツ用サーフェス解放 lpDDSParts[i]->Release(); if (lpDDSMessage) // メッセージウインドウサーフェス解放 lpDDSMessage->Release(); if (lpDDSChr) // 主人公用サーフェス解放 lpDDSChr->Release(); if (lpDDSMap) // マップ用サーフェス解放 lpDDSMap->Release(); if (lpDDSScreen) // 背景用サーフェス解放 lpDDSScreen->Release(); if (lpDDSBack) // バックバッファ解放 lpDDSBack->Release(); if (lpDDSPrimary) // プライマリサーフェス解放 lpDDSPrimary->Release(); if (lpDD) // DirectDrawオブジェクト解放 lpDD->Release(); PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }