⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directdraw.cpp

📁 diablo图形引擎例子
💻 CPP
字号:
// DirectDraw.cpp: implementation of the DirectDraw class.
//
//////////////////////////////////////////////////////////////////////


#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <windowsx.h>
#include "DirectDraw.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

DirectDraw::DirectDraw()
{
	m_lpDD=NULL;
	m_lpDDSPrimary=NULL;
	m_lpDDSBackbuffer=NULL;
	memset(&m_ddsd,0,sizeof(DDSURFACEDESC));
	m_ddsd.dwSize = sizeof (DDSURFACEDESC);
}

DirectDraw::~DirectDraw()
{
	if (m_lpDD!=NULL)                   
	{
	   if( m_lpDDSPrimary!=NULL)
        {
            m_lpDDSPrimary->Release();
            m_lpDDSPrimary= NULL;
        }
		m_lpDD->Release();
		m_lpDD=NULL;
	}
}

bool DirectDraw::Create(HWND hWnd)
{
	m_hWnd=hWnd;

	if (DirectDrawCreate(NULL, &m_lpDD, NULL)!=DD_OK)
		return false; 
	
#ifdef _DEBUG	
	if (m_lpDD->SetCooperativeLevel(m_hWnd,DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES) != DD_OK)
	{
		MessageBox(NULL,"协作层设置失败!","协作层设置失败!",MB_OK);
		return false;
	}
#else	
	if(m_lpDD->SetCooperativeLevel(m_hWnd,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)!=DD_OK)
	{
		MessageBox(NULL,"协作层设置失败 !","协作层设置失败 !",MB_OK);
		return false;
	}

	if (m_lpDD->SetDisplayMode(DisplayMode_Width,DisplayMode_Height,DisplayMode_ColorDeep)!=DD_OK)
	{
		MessageBox(NULL,"显示模式设置失败!","显示模式设置失败!",MB_OK);
		return false;
	}
#endif
	

	DDSURFACEDESC ddsd;
    HRESULT ddrval;

    // Create the primary surface with 1 back buffer
    memset( &ddsd, 0, sizeof(ddsd) );
    ddsd.dwSize = sizeof( ddsd );

#ifdef _DEBUG
    ddsd.dwFlags = DDSD_CAPS ;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE ;
    ddrval = m_lpDD->CreateSurface( &ddsd, &m_lpDDSPrimary, NULL );
    if( ddrval != DD_OK )	return FALSE;
	ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
	ddsd.dwWidth = DisplayMode_Width;
	ddsd.dwHeight = DisplayMode_Height;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;   // 创建后缓冲
    ddrval=m_lpDD->CreateSurface( &ddsd, &m_lpDDSBackbuffer, NULL );
#else 
    DDSCAPS ddscaps;
	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT ;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE  | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
	ddsd.dwBackBufferCount = 1;
    ddrval = m_lpDD->CreateSurface( &ddsd, &m_lpDDSPrimary, NULL );
    if( ddrval != DD_OK )	return FALSE;
    ddscaps.dwCaps = DDSCAPS_BACKBUFFER  ;
	ddrval = m_lpDDSPrimary->GetAttachedSurface(&ddscaps, &m_lpDDSBackbuffer);
#endif

	if( ddrval != DD_OK )    
	{
		MessageBox(NULL,"显示表面初始化失败 ! ","显示表面初始化失败 !",MB_OK);
		return false;
	}

	
#ifdef _DEBUG
	
	LPDIRECTDRAWCLIPPER  lpDDClipper;
	if (m_lpDD->CreateClipper( 0, &lpDDClipper, NULL ) != DD_OK )  
	{
		MessageBox(NULL,"Function: CreateClipper()...","剪裁器建立失败 !",MB_OK);
		return false;
	}
	if ( lpDDClipper->SetHWnd( 0, m_hWnd ) != DD_OK )   
	{
		MessageBox(NULL,"Function: Clipper->SetHWnd()","剪裁器窗口句柄设置失败 !",MB_OK);
		return false;
	}
    if ( m_lpDDSPrimary->SetClipper( lpDDClipper ) != DD_OK ) 
	{
		MessageBox(NULL,"Function: SetClipper()...","剪裁器连接到主表面失败 !",MB_OK);
		return false;
	}
    lpDDClipper->Release();

#endif
	
	DDPIXELFORMAT ddpf;  
	ddpf.dwSize=sizeof(DDPIXELFORMAT);
	if (m_lpDDSPrimary->GetPixelFormat( &ddpf )!=DD_OK)
	{
		MessageBox(NULL,"Function: GetPixelFormat()...","失败 !",MB_OK);
		return false;
	}    
	if (ddpf.dwGBitMask==0x3e0) 
		m_bColorMode=true;		//  000001111100000 555
	else
		m_bColorMode=false;	    // 0000011111100000 565

	return true;
}

bool DirectDraw::Lock(WORD * & lpBackbufferPtr, long & lPitch)
{
	m_lpDDSBackbuffer->Lock(NULL, &m_ddsd, DDLOCK_WAIT, NULL);
	//{
	///	return false;
	//} 
	//else
	//{
		lPitch  = m_ddsd.lPitch >> 1;	
		lpBackbufferPtr=(WORD *)m_ddsd.lpSurface;
		return true;
	//} 
}

bool DirectDraw::UnLock()
{
	if (m_lpDDSBackbuffer->Unlock(&m_ddsd)!=DD_OK)
		return false;
	else 
		return true;
}

void DirectDraw::Dump(char *lpBuffer)
{
	assert(lpBuffer);
	static DWORD time=GetTickCount();
	static int fps=0, frame=0, nt, ot=0;

	if ((GetTickCount()-time)>10)
	{
		time=GetTickCount();
		frame++;
		nt=GetTickCount(); 
		if (nt > ot+1000)
		{
			ot=nt;
			fps=frame;
			frame=0;
		} 
	}
	sprintf(lpBuffer,"帧数:%3.3d ",fps);
	if (m_bColorMode) strcat(lpBuffer,"555颜色模式");
	else strcat(lpBuffer,"565颜色模式");
}

void DirectDraw::Flip()
{
	HRESULT hResult;
#ifdef _DEBUG
	RECT src_rect, dst_rect;  
	POINT pt;  
	/*** src_rect is relative to offscreen buffer   */
	GetClientRect(m_hWnd,&src_rect);
	//GetClientRect( AfxGetMainWnd()->m_hWnd, &src_rect );   
	/*** dst_rect is relative to screen space so needs translation   */
	pt.x = pt.y = 0;   
	ClientToScreen( m_hWnd, &pt );   
	dst_rect = src_rect;
	dst_rect.left += pt.x;
	dst_rect.right += pt.x;
	dst_rect.top += pt.y;
    dst_rect.bottom += pt.y;   
	/*** perform the blit from backbuffer to primary, using ** src_rect and dst_rect */
	hResult=m_lpDDSPrimary->Blt(&dst_rect,m_lpDDSBackbuffer, &src_rect, DDBLT_WAIT,0);
	if (  hResult!= DD_OK )   
	{      
		// something bad happened
	}
#else 
	while( 1 )
	{
		hResult = m_lpDDSPrimary->Flip( NULL, DDFLIP_WAIT);
		if( hResult== DD_OK )
        {
			break;
		}
        if( hResult== DDERR_SURFACELOST )
        {
            hResult= Restore();
            if( hResult!= DD_OK )
            {
				break;
			}
        }
        if( hResult!= DDERR_WASSTILLDRAWING )
        {
            break;
        }
    }
#endif
}

void DirectDraw::DebugInfo()
{
	CleanDDSBackbuffer(RGB(0,0,0));

	HDC dc;char * temp=new char[256];

	m_lpDDSBackbuffer->GetDC(&dc);
	Dump(temp);
	TextOut(dc, 0, 0, temp, strlen(temp));
	m_lpDDSBackbuffer->ReleaseDC(dc);
	delete temp;

	//锁定表面测试
	WORD *lpBackbuffer=NULL;
	long lPitch;
	if (Lock(lpBackbuffer,lPitch))
	{
		for(int i=0;i<100;i++)
			*(lpBackbuffer+0+i*lPitch+i)=0x7fff;

		UnLock();
	}

	//翻转页面
    Flip();	
}

void DirectDraw::CleanDDSBackbuffer(DWORD Color)
{
	HRESULT hResult;
	DDBLTFX ddfx;
	ddfx.dwSize=sizeof(ddfx);
	ddfx.dwFillColor=Color;
	while(1)
	{
		hResult=m_lpDDSBackbuffer->Blt(NULL,NULL,NULL,DDBLT_COLORFILL,&ddfx);
		if( hResult == DD_OK )
        {
			break;
		}
		if( hResult== DDERR_SURFACELOST )
        {
            hResult= Restore();
            if( hResult!= DD_OK )
            {
				break;
			}
        }
        if( hResult!= DDERR_WASSTILLDRAWING )
        {
            break;
        }
	}
}

bool DirectDraw::Restore()
{
	if (m_lpDDSPrimary!=NULL) m_lpDDSPrimary->Restore();
	return true;
}


bool DirectDraw::Capture(char *lpszFilename)
{
   BITMAPFILEHEADER bmfh;
   BITMAPINFOHEADER bmih;
   FILE *fp=NULL;
 
   bmfh.bfType=0x4d42;
   bmfh.bfSize=0;
   bmfh.bfReserved1=0;
   bmfh.bfReserved2=0;
   bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

   bmih.biSize=sizeof(BITMAPINFOHEADER);
   bmih.biWidth=DisplayMode_Width;
   bmih.biHeight=DisplayMode_Height;
   bmih.biPlanes=1; 
   bmih.biBitCount=24;
   bmih.biCompression=BI_RGB; 
   bmih.biSizeImage=0;
   bmih.biXPelsPerMeter=0;
   bmih.biYPelsPerMeter=0; 
   bmih.biClrUsed=0;
   bmih.biClrImportant=0; 

   if ((fp=fopen(lpszFilename,"wb"))==NULL) return FALSE;

   fwrite(&bmfh,sizeof(bmfh),1,fp);
   fwrite(&bmih,sizeof(bmih),1,fp);
   
   //fseek(fp,bmfh.bfOffBits,SEEK_SET);

   //conver every pixel form 256 to 15bit
   	HDC hDC;
	
	m_lpDDSBackbuffer->GetDC(&hDC);

	for (int j=bmih.biHeight-1;j>=0;j--)
		for (int i=0;i<bmih.biWidth;i++)
		{	
			COLORREF c=GetPixel(hDC,i,j);
			BYTE r,g,b;
			r=GetRValue(c);
			g=GetGValue(c);
			b=GetBValue(c);
			fwrite(&b,1,1,fp);
			fwrite(&g,1,1,fp);
			fwrite(&r,1,1,fp);
		}
	m_lpDDSBackbuffer->ReleaseDC(hDC);

	fclose(fp);
	return TRUE;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -