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

📄 surface.cpp

📁 这个例子告诉你2d Arpg游戏中的动态阴影如何生成
💻 CPP
字号:
// Surface.cpp: implementation of the CSurface class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Surface.h"
#include "EasyDraw.h"
#include "log.h"
#include <stdio.h>
#define ENABLE_TRACE
//#define SafeRelease(x)	(if(x!=0) x->Release(); x=0)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Surface::Surface()
{
	Init();
}

Surface::Surface( Surface &surf )
{
	if(this!=&surf)
	{
		FreeSurface();
		this->m_ColorKeyType=surf.m_ColorKeyType;
		this->m_iHeight=surf.m_iHeight;
		this->m_iWidth=surf.m_iWidth;
		this->m_lpDDSurface=surf.m_lpDDSurface;
		this->m_lpDDSurfaceCopy=surf.m_lpDDSurfaceCopy;
	}
}


Surface::~Surface()
{

}

void Surface::Init()
{
	m_ColorKeyType = DDBLTFAST_NOCOLORKEY;
	m_lpDDSurface = NULL;
	m_lpDDSurfaceCopy = NULL;
	m_iWidth = 0;
	m_iHeight = 0;
}

void Surface::FreeSurface()
{
	if(m_lpDDSurface)
	{
		SafeRelease(m_lpDDSurface);
	}
	if(m_lpDDSurfaceCopy )
	{
		SafeRelease(m_lpDDSurfaceCopy);
	}
	m_ColorKeyType = DDBLTFAST_NOCOLORKEY;
	m_iWidth = 0;
	m_iHeight = 0;
}

bool Surface::GetWH( int *pWidth, int *pHeight )
{
	DDSURFACEDESC2 ddsd;
	ddsd.dwSize = sizeof( DDSURFACEDESC2 );

	if ( m_lpDDSurface != NULL )
	{
		if ( m_lpDDSurface->GetSurfaceDesc( &ddsd ) != DD_OK )
			return false;
	}
	else
		return false;
	
	if ( pWidth != NULL )
		*pWidth = ddsd.dwWidth;

	if ( pHeight != NULL )
		*pHeight= ddsd.dwHeight;
	return true;
}
//创建一个空页面
bool Surface::CreateNullSurface( int iw, int ih, bool isSysMemory, bool isColorKey, DWORD ColorKey )
{
	FreeSurface();

	HRESULT hr = CreateSurfaceHelp(	GetEasyDrawPointer()->GetLPDD(), 
									&m_lpDDSurface, iw, ih,
									isSysMemory, isColorKey, ColorKey );

	if ( hr == DDERR_OUTOFVIDEOMEMORY )
	{
		isSysMemory = true;
	}

	return OnCreateSurface( isSysMemory, isColorKey );
}

bool Surface::CreateImageSurface( char *szFileName, bool isSysMemory, bool isColorKey, DWORD ColorKey )
{
	if ( szFileName != NULL )
	{
		int len = strlen(szFileName);
		char szNameEx[3];
		strcpy( szNameEx, &szFileName[len-3] );
		
		if ( strcmp( szNameEx, "BMP" ) == 0 || strcmp( szNameEx, "bmp" ) == 0 )
		{
			return CreateBmpSurface( szFileName, isSysMemory, isColorKey, ColorKey );
		}
		else 
			return false;
	}
	
	return false;
}

bool Surface::CreateBmpSurface( char *szFileName, bool isSysMemory, bool isColorKey, DWORD ColorKey )
{
	FreeSurface();
	LPDIRECTDRAW7 lpdd = GetEasyDrawPointer()->GetLPDD(); 

	HRESULT hr = CreateSurfaceOfBmp( lpdd, &m_lpDDSurface, szFileName, isSysMemory, isColorKey, ColorKey );
	
	if ( hr == DDERR_OUTOFVIDEOMEMORY )
		isSysMemory = true;

	return OnCreateSurface( isSysMemory, isColorKey );
}

bool Surface::OnCreateSurface( bool isSysMemory, bool isColorKey )
{
	if ( m_lpDDSurface == NULL )
		return false;
	
	GetWH( &m_iWidth, &m_iHeight );
	if ( isColorKey )
	{
		m_ColorKeyType = DDBLTFAST_SRCCOLORKEY;
	}

	if ( !isSysMemory )
		return CreateCopySurface();
	else
		return true;
}

bool Surface::CreateCopySurface()
{
	if ( m_lpDDSurface == NULL )
		return false;

	SafeRelease(m_lpDDSurfaceCopy);
	CreateSurfaceHelp( GetEasyDrawPointer()->GetLPDD(), &m_lpDDSurfaceCopy, m_iWidth, m_iHeight, true, false, 0 );
	if ( m_lpDDSurfaceCopy == NULL )
		return false;

	m_lpDDSurfaceCopy->BltFast( 0, 0, m_lpDDSurface, NULL, DDBLTFAST_NOCOLORKEY );

	return true;
}
//绘制页面到后台缓冲区
void Surface::DrawSurface( int x, int y, RECT *pRect )
{
	LPDIRECTDRAWSURFACE7 lpDDBack = GetEasyDrawPointer()->GetBackSurface();

	if ( m_lpDDSurface != NULL )
	{
		lpDDBack->BltFast( x, y, m_lpDDSurface, pRect, m_ColorKeyType );
	}
}

void Surface::DrawNight( int x, int y, RECT *pRect )
{
	LPDIRECTDRAWSURFACE7 lpDDBack = GetEasyDrawPointer()->GetBackSurface();

	if ( m_lpDDSurfaceCopy != NULL )
	{
		lpDDBack->BltFast( x, y, m_lpDDSurfaceCopy, pRect, m_ColorKeyType );
	}
}

//剪裁绘制页面到后台缓冲区
void Surface::DrawAutoClip( int x, int y )
{
	int iSW = GetEasyDrawPointer()->GetDeviceWidth();
	int iSH = GetEasyDrawPointer()->GetDeviceHeight();

	RECT rc;
	rc.left = 0;
	rc.top	= 0;
	rc.right= m_iWidth;
	rc.bottom=m_iHeight;

	if ( x + m_iWidth > iSW ) 
	{
		rc.right -= x + m_iWidth - iSW;
	}
	else if ( x < 0 ) 
	{
		rc.left -= x;
		x = 0;
	}

	if ( y + m_iHeight > iSH ) 
	{
		rc.bottom -= y + m_iHeight - iSH;
	}
	else if ( y < 0 ) 
	{
		rc.top -= y;
		y = 0;
	}
 
	LPDIRECTDRAWSURFACE7 lpDDBack = GetEasyDrawPointer()->GetBackSurface();
	lpDDBack->BltFast( x, y, m_lpDDSurface, &rc, m_ColorKeyType );
}
//页面恢复
bool Surface::Restore()
{
	if ( m_lpDDSurface == NULL )
		return false;

	HRESULT hr;
	hr = m_lpDDSurface->IsLost();
	if ( hr != DD_OK )
	{
		hr = m_lpDDSurface->Restore();
		if ( hr != DD_OK )
			return false;
	}

	if ( m_lpDDSurfaceCopy != NULL )
		m_lpDDSurface->BltFast( 0, 0, m_lpDDSurfaceCopy, NULL, DDBLTFAST_NOCOLORKEY );

	return true;
}
//从一个页面画到其他的页面
void Surface::BltTo( int destX, int destY, Surface *pDestSurf, RECT *rcSrc )
{
	//目的页面不空且原页面不空
	if ( pDestSurf->m_lpDDSurface != NULL && m_lpDDSurface != NULL )
	{
		pDestSurf->m_lpDDSurface->BltFast( destX, destY, m_lpDDSurface, rcSrc, m_ColorKeyType );

			//拷贝页面绘制
		if ( pDestSurf->m_lpDDSurfaceCopy != NULL )
			pDestSurf->m_lpDDSurfaceCopy->BltFast( destX, destY, m_lpDDSurface, rcSrc, m_ColorKeyType );
	}
}
//向页面上写字
void Surface::WriteText( const char *szText, int TextLen, int x, int y, DWORD Color )
{
	if ( m_lpDDSurfaceCopy != NULL )
	{
//		DrawTextOnSurface( m_lpDDSurfaceCopy, szText, TextLen, x, y, Color ); 
		Restore();
	}
	else if ( m_lpDDSurface != NULL )
	{
//		DrawTextOnSurface( m_lpDDSurface, szText, TextLen, x, y, Color ); 
	}
}

void Surface::SetSurfaceColorKey( DWORD ColorKey )
{
	if ( !m_lpDDSurface == NULL )
	{
		ColorKey = GetEasyDrawPointer()->ChangeColorKey( ColorKey );
		SetColorKeyHelp( m_lpDDSurface, ColorKey );
		m_ColorKeyType = DDBLTFAST_SRCCOLORKEY;
	}
}

bool Surface::CopySurface( Surface * psurf )
{
	if ( m_lpDDSurface == NULL )
		return false;

	SafeRelease(m_lpDDSurfaceCopy);
	CreateSurfaceHelp( GetEasyDrawPointer()->GetLPDD(), &m_lpDDSurfaceCopy, m_iWidth, m_iHeight, true, false, 0 );
	if ( m_lpDDSurfaceCopy == NULL )
		return false;

	m_lpDDSurfaceCopy->BltFast( 0, 0, m_lpDDSurface, NULL, DDBLTFAST_NOCOLORKEY );

	return true;
}

bool Surface::CopySurfaceToBmp( char *szBmpName, RECT *pRect )
{
	if ( m_lpDDSurface != NULL )
	{
		return CopySurfaceToBmp16( m_lpDDSurface, szBmpName, pRect, true );
	}
	else
		return false;
}

void Surface::DrawAlphaMMX( int x, int y )
{
	if ( m_lpDDSurface == NULL )
		return;
	RECT rc_src;		//temp页面上要锁定的矩形区域
	RECT rc;			//temp页面上要blt的区域
	RECT rc_dest;		//目标页面上的矩形区域

	rc_src.left = 0;
	rc_src.top  = 0;
	rc_src.right= m_iWidth;
	rc_src.bottom=m_iHeight;

	rc = rc_src;

	int iSW = GetEasyDrawPointer()->GetDeviceWidth();
	int iSH = GetEasyDrawPointer()->GetDeviceHeight();

	if ( x + m_iWidth > iSW ) 
		rc.right -= x + m_iWidth - iSW;

	if ( x < 0 ) 
	{
		rc.left -= x;
		x = 0;
	}

	if ( y + m_iHeight > iSH ) 
		rc.bottom -= y + m_iHeight - iSH;

	if ( y < 0 ) 
	{
		rc.top -= y;
		y = 0;
	}

	rc_dest.left = x;
	rc_dest.top	= y;
	rc_dest.right= x + rc.right - rc.left;
	rc_dest.bottom=y + rc.bottom- rc.top;

	LPDIRECTDRAWSURFACE7 back, temp;
	back = GetEasyDrawPointer()->GetBackSurface();
	temp = GetEasyDrawPointer()->GetTempSurface();

	//test
//	char str[128];
//	sprintf(str,"%d,%d,%d,%d",rc_dest.left,rc_dest.top,rc_dest.right,rc_dest.bottom);
//	CODE_TRACE("surface.cpp",str);
	//test end

	//把后台页面的矩形拷贝到特效页面上
	temp->BltFast( rc.left, rc.top, back, &rc_dest, DDBLTFAST_NOCOLORKEY );

	//锁定特效页面
	DDSURFACEDESC2 ddsd;

	ddsd.dwSize = sizeof(ddsd);
	if ( temp->Lock( &rc_src, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK )		return;
	WORD *buf_temp = (WORD *)ddsd.lpSurface;
	int pitch_temp = ddsd.lPitch;

	//锁定内存页面
	ddsd.dwSize = sizeof(ddsd);
	if ( m_lpDDSurface->Lock( NULL, &ddsd, DDLOCK_READONLY, NULL ) != DD_OK )
	{
		temp->Unlock(0);
		return;
	}
	
	WORD *buf_surf = (WORD *)ddsd.lpSurface;
	ddsd.dwWidth *= 2;
	int pitch_surf = ddsd.lPitch - ddsd.dwWidth;
	pitch_temp -= ddsd.dwWidth;

	__int64 _0x7befx4 = 0x7bef7bef7bef7bef;
	__asm
	{	
		mov edx, buf_temp;				//edx 目标页面指针
		mov ecx, buf_surf;				//ecx 源页面指针
		xor ebx, ebx;

_for_h_begin:
		cmp ebx, ddsd.dwHeight;
		jnb _for_h_end;

		xor eax, eax;

_for_w_begin:
		cmp eax, ddsd.dwWidth;
		jnb _for_w_end;

		movq mm0, [edx];
		movq mm1, [ecx];
		psrlw mm0, 1;
		psrlw mm1, 1;
		pand mm0, _0x7befx4;
		pand mm1, _0x7befx4;
		paddusw mm0, mm1;			//注意要用paddusw无符号饱和压缩加法
		movq [edx], mm0;

		add edx, 8;
		add ecx, 8;
		add eax, 8;
		jmp _for_w_begin;

_for_w_end:
		inc ebx;
		add edx, pitch_temp;
		add ecx, pitch_surf;
		jmp _for_h_begin;
_for_h_end:
		emms;
	}

	m_lpDDSurface->Unlock(0);
	temp->Unlock(0);
	back->BltFast( x, y, temp, &rc, DDBLTFAST_NOCOLORKEY ); 
}

//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
void Surface::DrawAlphaShadow( int x, int y )
{
	if ( m_lpDDSurface == NULL )
		return;
	RECT rc_src;		//temp页面上要锁定的矩形区域
	RECT rc;			//temp页面上要blt的区域
	RECT rc_dest;		//目标页面上的矩形区域

	rc_src.left = 0;
	rc_src.top  = 0;
	rc_src.right= m_iWidth;
	rc_src.bottom=m_iHeight;

	rc = rc_src;

	int iSW = GetEasyDrawPointer()->GetDeviceWidth();
	int iSH = GetEasyDrawPointer()->GetDeviceHeight();

	if ( x + m_iWidth > iSW ) 
		rc.right -= x + m_iWidth - iSW;

	if ( x < 0 ) 
	{
		rc.left -= x;
		x = 0;
	}

	if ( y + m_iHeight > iSH ) 
		rc.bottom -= y + m_iHeight - iSH;

	if ( y < 0 ) 
	{
		rc.top -= y;
		y = 0;
	}

	rc_dest.left = x;
	rc_dest.top	= y+m_iHeight/2;
	rc_dest.right= x + 2*m_iWidth;
	rc_dest.bottom=y + m_iHeight;


	if ( rc_dest.right > iSW ) 
		rc_dest.right -= (rc_dest.right - iSW);

	if ( rc_dest.left < 0 ) 
	{
		rc_dest.left=0;
	}

	if ( rc_dest.bottom > iSH ) 
		rc.bottom -= (rc_dest.bottom - iSH);

	if ( rc_dest.top < 0 ) 
	{
		rc_dest.top=0;
	}


	LPDIRECTDRAWSURFACE7 back, temp;
	back = GetEasyDrawPointer()->GetBackSurface();
	temp = GetEasyDrawPointer()->GetTempSurface();

	//把后台页面的矩形拷贝到特效页面上
	temp->BltFast( rc.left, rc.top, back, &rc_dest, DDBLTFAST_NOCOLORKEY );

//	DDBLTFX ddBltFx;
//	ddBltFx.dwSize=sizeof(DDBLTFX);
//	ddBltFx.dwFillPixel=0;
//	ddBltFx.dwFillColor =0xffff;
//	temp->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);
//	DDCOLORKEY ddck;
//	ddck.dwColorSpaceLowValue = 0xffff;
//	ddck.dwColorSpaceHighValue = 0xffff;
//	temp->SetColorKey( DDCKEY_SRCBLT, &ddck );
//	m_lpDDSurfaceCopy->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);
//	char str[32];
//	sprintf(str,"%d %d %d %d",rc_dest.left,rc_dest.top,rc_dest.right,rc_dest.bottom);
//	log::instance().dump("surface.cpp",str);
	//锁定特效页面
	DDSURFACEDESC2 ddsdtemp;
	WORD *buf_temp;
	int pitch_temp;

	rc_src.left=0;
	rc_src.right=rc_dest.right-rc_dest.left;
	rc_src.top=0;
	rc_src.bottom=rc_dest.bottom-rc_dest.top;

	ddsdtemp.dwSize = sizeof(ddsdtemp);
	if ( temp->Lock( &rc_src, &ddsdtemp, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK )		
			return;
	buf_temp = (WORD *)ddsdtemp.lpSurface;
	pitch_temp = ddsdtemp.lPitch;
	ddsdtemp.lPitch=ddsdtemp.lPitch >> 1;
	//锁定内存页面
	DDSURFACEDESC2 ddsdsurf;
        WORD *buf_surf;
	ddsdsurf.dwSize = sizeof(ddsdsurf);
	if ( m_lpDDSurface->Lock( NULL, &ddsdsurf, DDLOCK_READONLY, NULL ) != DD_OK )
	{
		temp->Unlock(0);
		return;
	}
	ddsdsurf.lPitch=ddsdsurf.lPitch >> 1;
	buf_surf = (WORD *)ddsdsurf.lpSurface;

	WORD *buf = buf_temp;
	__int64 _0x7befx4 = 0x7bef7bef7bef7bef;
	WORD *data = buf_surf;

	int Width=rc_dest.right-rc_dest.left;
	
	WORD mask=0x7bef;
	for(int i=m_iHeight/2;i>0;i--)
	{
		data =buf_surf;
		buf = buf_temp;
		int bujin=(2*i*m_iWidth)/m_iHeight;
		buf+=bujin;
		int kuandu=Width-bujin;
		if(kuandu>m_iWidth)
		{
			kuandu=m_iWidth;
		}
		for(int x=0;x<kuandu;x++)
		{
			if((*data)!=0x0000)
		//	{
				_asm
				{
				
					mov eax,buf;
					mov bx,7befh;
					mov cx,[eax]
					shr cx,1;
					and cx,bx;
					mov [eax],cx;
				}
		//	}
			data++;
			buf++;
		}
		buf_temp+=ddsdtemp.lPitch;
		buf_surf+=ddsdsurf.lPitch;
		buf_surf+=ddsdsurf.lPitch;
	}

	m_lpDDSurface->Unlock(0);
	temp->Unlock(0);
	back->BltFast( x, y+m_iHeight/2, temp, &rc_src, DDBLTFAST_NOCOLORKEY ); 
}

inline void BrightnessAndContrast1(int& red,int& green,int& blue,
		int contrast,int brightness)
{
		static int old_c = 0,old_b = 0;
		static int extra_c = 0;
		static float ratio = 0;
		if( contrast!=old_c ) 
		{
			ratio = (float)contrast/100; 
			extra_c = -127*ratio;
			old_c = contrast;
		}
		if( brightness!=old_b) 
		{
			extra_c += brightness;
			old_b = brightness;
		}

		red		-= red*ratio	+ extra_c;
		green	-= green*ratio	+ extra_c;
		blue	-= blue*ratio	+ extra_c;

		if(red>255) red=255;
		if(green>255) green=255;
		if(blue>255) blue=255;

		if(red<0) red=0;
		if(green<0) green=0;
		if(blue<0) blue=0;
}

#define _MY16RGB565(r,g,b) ((b>>3) + ( (g>>2)<< 5 ) + ( (r>>3)<<11 ))

void Surface::CreateNight()
{
	//锁定特效页面
	DDSURFACEDESC2 ddsd;



	//锁定内存页面
	ddsd.dwSize = sizeof(ddsd);
	if (this->m_lpDDSurfaceCopy->Lock( NULL, &ddsd, DDLOCK_READONLY, NULL ) != DD_OK )
	{
		this->m_lpDDSurfaceCopy->Unlock(0);
		return;
	}

	WORD *buf_surf = (WORD *)ddsd.lpSurface;
	ddsd.dwWidth *= 2;
	int pitch_surf = ddsd.lPitch - ddsd.dwWidth;

	int size=ddsd.lPitch>>1;
	WORD *buffer=(USHORT *)ddsd.lpSurface;
	for(int x=0;x<960;x++)
	{
			for(int y=0;y<640;y++)
			{
		
				int value = buffer[y*size+x];
				int red  = (value & 0x0000f800)>>8,
					green= (value & 0x000007e0)>>3,
					blue = (value & 0x0000001f)<<3;
				BrightnessAndContrast1(red,green,blue,55,85);
				buffer[y*size+x] = _MY16RGB565(red,green,blue);
			}
	}
	this->m_lpDDSurfaceCopy->Unlock(0);
}

⌨️ 快捷键说明

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