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

📄 easydraw.cpp

📁 这个例子告诉你2d Arpg游戏中的动态阴影如何生成
💻 CPP
字号:
#include "stdafx.h"
#include "EasyDraw.h"
#include <windowsx.h>
#include <stdio.h>

EasyDraw theEasyDraw;

EasyDraw::EasyDraw()
{
	lpDD			= NULL;
	lpDDSBack		= NULL;
	lpDDSPrimary	= NULL;
	lpDDSTemp		= NULL;
	GameHwnd		= NULL;				//一个离屏页面,用于完成各种特效
}

EasyDraw::~EasyDraw()
{
	if ( lpDD != NULL )
	{
		SafeRelease(lpDDSTemp);
		SafeRelease(lpDDSBack);
		SafeRelease(lpDDSPrimary);
		lpDD->SetCooperativeLevel( GameHwnd, DDSCL_NORMAL );

		SafeRelease(lpDD);
		GameHwnd = NULL;
	}	
}
//565转555
DWORD EasyDraw::ChangeColorKey( DWORD colorkey )
{
	DWORD w = colorkey;

//	return CHANGE_565_TO_555( w );

	return w;
}

bool EasyDraw::InitDDraw(HWND hwnd, bool isWindowed, int iW, int iH)
{
	m_iWidth=iW;
	m_iHeight=iH;
	DDSURFACEDESC2 ddsd; // DirectDraw的页面描述

	HRESULT hr;

	//创建lpdd7对象:
	hr = DirectDrawCreateEx(NULL, (void **)&lpDD, IID_IDirectDraw7, NULL); 
	if ( hr != DD_OK )
	{
		return false;
	}

	SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );

	hr = lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
	if ( hr != DD_OK )
	{
		return false;
	}
	//设置屏幕模式:
	hr = lpDD->SetDisplayMode( iW, iH, 16, 0, 0 );				//只支持16位模式
	if ( hr != DD_OK )
	{
		return false;
	}

	//创建主页面:
	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;
	
	hr = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
	if ( hr != DD_OK )
	{
		return false;
	}
	
	//创建后台页面:
	DDSCAPS2 ddscaps;
	ZeroMemory( &ddscaps, sizeof( ddscaps ) );
	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
	hr = lpDDSPrimary->GetAttachedSurface( &ddscaps, &lpDDSBack );
	if ( hr != DD_OK )
	{
		return false;
	}
		ddsd.dwSize = sizeof( ddsd );
		ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT; 
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; //这是离屏页面
		ddsd.dwHeight=300; //高
		ddsd.dwWidth=300; //宽
		if ( DD_OK != lpDD->CreateSurface( &ddsd, &lpDDSTemp, NULL ) )
			return FALSE; //创建放背景图的页面
		//如还有别的页面可在此处继续创建
		return TRUE;
}
void EasyDraw::Filp()
{
//	RECT rect={0,0,1024,768};
	RECT rect={0,0,800,600};
	lpDDSPrimary->BltFast( 0, 0,this->lpDDSBack,&rect, DDBLTFAST_NOCOLORKEY );
}
//-------------------------------------------------EasyDraw辅助函数------------------------------------------------------
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
EasyDraw * InitEasyDraw( HWND hwnd, bool isWindowed, int iW, int iH )
{
	if ( theEasyDraw.InitDDraw( hwnd, isWindowed, iW, iH ) == false )
	{
		return NULL;
	}

	return &theEasyDraw;
}

EasyDraw *GetEasyDrawPointer()
{
	return &theEasyDraw;
}
//////////////////////////////////////////////////////////////////////
//是否有关键色
//////////////////////////////////////////////////////////////////////

void SetColorKeyHelp( LPDIRECTDRAWSURFACE7 lpDDSurface, DWORD ColorKey)
{
	DDCOLORKEY ddck;
	ddck.dwColorSpaceLowValue = ColorKey;
	ddck.dwColorSpaceHighValue = ColorKey;
	lpDDSurface->SetColorKey( DDCKEY_SRCBLT, &ddck );
}
//////////////////////////////////////////////////////////////////////
//创建一个离屏页面
//参数:页面宽高,是否使用系统内存,是否有关键色
//////////////////////////////////////////////////////////////////////
HRESULT CreateSurfaceHelp( LPDIRECTDRAW7 lpdd,
						   LPDIRECTDRAWSURFACE7 *ppSurface,
						   int iW, int iH, 
						   bool isSysMemory, bool isColorKey, 
						   DWORD ColorKey )
{
	if ( ppSurface == NULL )
		return E_FAIL;

	LPDIRECTDRAWSURFACE7 lpDDSurface = NULL;
	DDSURFACEDESC2 ddsd;
	ZeroMemory( &ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

	if ( isSysMemory )
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
	else
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;

	ddsd.dwWidth = iW;
	ddsd.dwHeight = iH;

	HRESULT hr;
	hr = lpdd->CreateSurface( &ddsd, &lpDDSurface, NULL );

	if ( hr == DDERR_OUTOFVIDEOMEMORY )						//如果显存不足,将在内存中分配页面
	{
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
		hr = lpdd->CreateSurface( &ddsd, &lpDDSurface, NULL );

		if ( hr != DD_OK )
			return hr;
		else
			hr = DDERR_OUTOFVIDEOMEMORY;					//如果在内存中分配成功,返回DDERR_OUTOFVIDEOMEMORY
	}



	//设置关键色
	if ( isColorKey )
		SetColorKeyHelp( lpDDSurface, ColorKey );
	*ppSurface = lpDDSurface;
	return hr;
}


HRESULT CreateSurfaceOfBmp( LPDIRECTDRAW7 lpdd, 
							LPDIRECTDRAWSURFACE7 *ppSurface,
							char *szFileName, 
							bool isSysMemory, 
							bool isColorKey, DWORD ColorKey )
{	
	if ( ppSurface == NULL )
		return E_FAIL;

	LPDIRECTDRAWSURFACE7 lpDDSurface = NULL;
	HBITMAP hBmp;
	

	hBmp = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );


	if ( hBmp == NULL )
		return E_FAIL;
	BITMAP bmp;
	GetObject( hBmp, sizeof(bmp), &bmp );
	
	HRESULT hr = CreateSurfaceHelp( lpdd, &lpDDSurface, bmp.bmWidth, bmp.bmHeight, isSysMemory, isColorKey, ColorKey );

	if ( lpDDSurface == NULL )
		return hr;

	if ( LoadBmpToSurfaceFromHBmp( hBmp, lpDDSurface, 0, 0 ) == NULL )
	{
		lpDDSurface->Release();
		lpDDSurface=NULL;
		return E_FAIL;
	}

	*ppSurface = lpDDSurface;
	return hr;
}

LPDIRECTDRAWSURFACE7 LoadBmpToSurfaceFromHBmp( HBITMAP hBmp, 
											   LPDIRECTDRAWSURFACE7 lpDDSurface, 
											   int x, int y )
{	

    HDC            hDCImage;
    HDC            hDC;
    BITMAP         bmp;
    DDSURFACEDESC2 ddsd;
    HRESULT        hr;

    if( hBmp == NULL || lpDDSurface == NULL )
        return NULL;

    if( FAILED( hr = lpDDSurface->Restore() ) )
        return NULL;

    ddsd.dwSize  = sizeof(ddsd);
    lpDDSurface->GetSurfaceDesc( &ddsd );

    if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC )
        return NULL;

    hDCImage = CreateCompatibleDC( NULL );
    if( NULL == hDCImage )
        return NULL;

    SelectObject( hDCImage, hBmp );

    GetObject( hBmp, sizeof(bmp), &bmp );
 
    if( FAILED( hr = lpDDSurface->GetDC( &hDC ) ) )
        return NULL;

	BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, hDCImage, 0, 0, SRCCOPY );

    if( FAILED( hr = lpDDSurface->ReleaseDC( hDC ) ) )
        return NULL;

    DeleteDC( hDCImage );					//此处并没有DeleteObject( hBmp )

    return lpDDSurface;
}

bool CopySurfaceToBmp16( LPDIRECTDRAWSURFACE7 lpDDSurface, char *szFileName, RECT *pRect, bool is565 )
{
	debug_assert( lpDDSurface != NULL && szFileName != NULL );

	DDSURFACEDESC2 ddsd;
	WORD *lpBuffer;				//指向页面的指针
	int iPitch;	
	int iResidue	= 0;		//补上的可以被4整除的数,单位字节
	int iW			= 0;
	int iH			= 0;

	
	BITMAPFILEHEADER	bmfh;	//位图的文件头
	BITMAPINFOHEADER	bmih;	//位图信息头
	DWORD dwRMask	= 0xf800;	//565的遮码
	DWORD dwGMask	= 0x07e0;
	DWORD dwBMask	= 0x001f;

	if ( !is565 )				//如果显示模式不是565的话
	{
		dwRMask = 0x7c00;
		dwGMask = 0x03e0;
	}

	FILE *fp = fopen( szFileName, "wb+" );
	if ( fp == NULL )
		return false;

	//锁定主页面:
	ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了
	if ( lpDDSurface->Lock( pRect, &ddsd, 
		DDLOCK_SURFACEMEMORYPTR | DDLOCK_READONLY | DDLOCK_WAIT, NULL ) != DD_OK )
	{
		fclose(fp);
		return false;
	}
	
	lpBuffer = (WORD *)ddsd.lpSurface;  //注意这里有个类型转换
	iPitch = ddsd.lPitch >> 1;

	if ( pRect == NULL )
	{
		iW = ddsd.dwWidth;
		iH = ddsd.dwHeight;
	}
	else
	{
		iW = pRect->right - pRect->left;
		iH = pRect->bottom- pRect->top;
	}
	iResidue = (iW % 2) * 2;			//计算出补数 

	//写入文件头:
	bmfh.bfType = 'MB';					//注意这里是MB,而不是BM
	bmfh.bfSize = 0x36 + 12 + ( iW + iResidue / 2 ) * iH * 2;
	bmfh.bfOffBits = 0x36 + 12;
	bmfh.bfReserved1 = 0;
	bmfh.bfReserved2 = 0;

	fwrite( &bmfh, sizeof(bmfh), 1, fp );

	//写入信息头:
	bmih.biSize = sizeof(BITMAPINFOHEADER); 
	bmih.biWidth = iW;
	bmih.biHeight = iH;
	bmih.biPlanes = 1;
	bmih.biBitCount = 16;	
	bmih.biCompression = BI_BITFIELDS;	//16位的565格式,若为其它格式,图像失真
	bmih.biSizeImage = ( iW + iResidue / 2 ) * iH * 2;
	bmih.biXPelsPerMeter = 0;
	bmih.biYPelsPerMeter = 0;
	bmih.biClrUsed = 0;
	bmih.biClrImportant = 0;

	fwrite( &bmih, sizeof(bmih), 1, fp );
	fwrite( &dwRMask, 4, 1, fp );
	fwrite( &dwGMask, 4, 1, fp );
	fwrite( &dwBMask, 4, 1, fp );				//写入遮码			


	//开始写入数据:
	fseek( fp, 0x36+12, SEEK_SET );

	for ( int i = iH - 1; i >= 0; i-- )					//i为高
	{
		for ( int j = 0; j < iW; j++ )			//j为宽
		{
			WORD word = lpBuffer[ i * iPitch + j ];
			fwrite( &word, 2, 1, fp );
		}	
		fseek( fp, iResidue, SEEK_CUR );		//跳过补数部份
	}

	lpDDSurface->Unlock( NULL );
	fclose(fp);
	return true;
}

⌨️ 快捷键说明

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