📄 gp_draw.cpp
字号:
if( ddrval == DD_OK )
{
x=ddsd.dwWidth;
y=ddsd.dwHeight;
return ddsd.lPitch>>1; //不说了
}
return false;
}
//****************************
//获取一个表面的宽度
int GetSurfaceWidth(LPDIRECTDRAWSURFACE surf)
{
DDSURFACEDESC ddsd;
HRESULT ddrval;
ddsd.dwSize=sizeof(ddsd);
ddrval=surf->GetSurfaceDesc(&ddsd);
if( ddrval == DD_OK )
{
return ddsd.dwWidth;
}
return false;
}
//****************************
//获取一个表面的高度
int GetSurfaceHeight(LPDIRECTDRAWSURFACE surf)
{
DDSURFACEDESC ddsd;
HRESULT ddrval;
ddsd.dwSize=sizeof(ddsd);
ddrval=surf->GetSurfaceDesc(&ddsd);
if( ddrval == DD_OK )
{
return ddsd.dwHeight;
}
return false;
}
//************************************
//开页面缓冲区,然后直接在缓冲区中操作
bool BeginDraw(LPDIRECTDRAWSURFACE lpSur)
{
ddsd.dwSize = sizeof(ddsd);
while( 1 )
{
ddrval = lpSur->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ); //锁定
if( ddrval == DD_OK )
{
break;
}
if( ddrval == DDERR_SURFACELOST )
{
ddrval = restoreAll();
if( ddrval != DD_OK ) return( false );
}
}
GraphBuffer = (WORD *)ddsd.lpSurface; //内存指针
GraphWidth = ddsd.dwWidth; //宽度
GraphHeight = ddsd.dwHeight; //高度
GraphPitch = ddsd.lPitch >> 1; //lPitch以Byte为单位计数的,
//GraphPitch以WORD为单位。所以GraphPitch = lPitch / 2;
return( true );
}
//******************
//关闭缓冲区
bool EndDraw(LPDIRECTDRAWSURFACE lpSur)
{
ddrval = lpSur->Unlock( NULL ); //解锁
if( ddrval != DD_OK ) return( false );
return true;
}
//--------------------------------------------------------------//
//////////////////////////////////////////////////////////////////
//--------------------------------------------------------------//
//功能:以单色填充页面
//参数:目标表面,颜色
void FillSurface(LPDIRECTDRAWSURFACE surf, DWORD color)
{
WORD color16=RGB16(color); //转化成16色
if( BeginDraw(surf) )
{
for( int i=0; i<GraphHeight; i++)
for(int j=0; j<GraphWidth; j++)
GraphBuffer[i*GraphPitch+j] = color16; //直接填充
EndDraw(surf);
}
}
//以单色填充页面
void FillSurface(LPDIRECTDRAWSURFACE surf, WORD color)
{
if( BeginDraw(surf) )
{
for( int i=0; i<GraphHeight; i++)
for(int j=0; j<GraphWidth; j++)
GraphBuffer[i*GraphPitch+j] = color; //直接填充
EndDraw(surf);
}
}
//--------------------------------------------------------------//
//////////////////////////////////////////////////////////////////
//--------------------------------------------------------------//
//功能:特效淡入
//参数:风格,延时(缺省),颜色(缺省)
void FadeIn(int Style, int time, WORD Color)
{
switch( Style )
{
case 0: //无效果
break;
case 1: //百叶窗
ScreenIn();
break;
case 2: //淡入淡出
ColorIn(time, Color);
break;
}
}
//功能:特效淡出
//参数:风格,延时(缺省),目标表面(缺省)
void FadeOut(int Style, int time, LPDIRECTDRAWSURFACE lpSurf)
{
switch( Style )
{
case 0: //无效果
break;
case 1: //百叶窗
ScreenOut(lpSurf);
break;
case 2: //淡入淡出
ColorOut(lpSurf, time);
break;
}
}
//--------------------------------------------------------------//
//////////////////////////////////////////////////////////////////
//--------------------------------------------------------------//
//淡入(time=每一帧的时间)
void ColorIn(int time, WORD Color)
{
unsigned int alpha=2, oldtick, newtick;
WORD *lpSurf, *lpTemp, BlackColor=Color;
//建立临时页面
LPDIRECTDRAWSURFACE Temp;
CreateBitmap(Temp, ScreenWidth, ScreenHeight);
//保存到临时页面
if( WindowMode==0 ) //全屏
Blt(Temp, 0, 0, lpDDSPrimary, RectScreen, false);
else
Blt(Temp, 0, 0, lpDDSPrimary, RectWindow, false);
if( BeginDraw(lpDDSBack) )
{
lpSurf=GraphBuffer;
EndDraw(lpDDSBack);
}
if( BeginDraw(Temp) )
{
lpTemp=GraphBuffer;
EndDraw(Temp);
}
oldtick=timeGetTime(); //起始时间
for(int i=0; i<16; i++)
{
//把主表面的点和传近来的点进行alpha混合到lpDDSBack
for(int j=0; j<ScreenWidth*ScreenHeight; j++)
{
lpSurf[j]=Alpha_Pixel(BlackColor, lpTemp[j], alpha);
}
//延时
newtick=timeGetTime();
while( newtick-oldtick < (unsigned int)(time * i) )
{
newtick=timeGetTime();
}
//更新屏幕
_UpdateScreen();
//自动跳桢
i=(newtick-oldtick)/time;
//alpha增加
alpha=i*2+2;
if( i >= 15 ) //结束
{
alpha=31;
for(int j=0; j<ScreenWidth*ScreenHeight; j++)
{
lpSurf[j]=Alpha_Pixel(BlackColor, lpTemp[j], alpha);
}
_UpdateScreen();
break;
}
}
//释放
_RELEASE( Temp );
}
//淡出(time=每一帧的时间)
void ColorOut(LPDIRECTDRAWSURFACE dest, int time)
{
unsigned int alpha=2, oldtick, newtick;
WORD *lpSour, *lpDest, *lpBack;
if( WindowMode != 0 ) //窗口
{
Blt(lpDDSSour, 0,0, lpDDSPrimary, RectWindow, false);
}
else
{
Blt(lpDDSSour, 0,0, lpDDSPrimary, RectScreen, false);
}
if( BeginDraw(lpDDSSour) )
{
lpSour=GraphBuffer;
EndDraw(lpDDSSour);
}
if( BeginDraw(dest) )
{
lpDest=GraphBuffer;
EndDraw(dest);
}
if( BeginDraw(lpDDSTemp) )
{
lpBack=GraphBuffer;
EndDraw(lpDDSTemp);
}
oldtick=timeGetTime();
for(int i=0; i<16; i++)
{
for(int j=0; j<ScreenWidth*ScreenHeight; j++)
{
//看看上面的函数对比一下
//这个是从屏幕逐渐变化到dest页面
lpBack[j]=Alpha_Pixel(lpDest[j], lpSour[j], alpha);
}
//延时
newtick=timeGetTime();
while( newtick-oldtick < (unsigned int)(time*i) )
{
newtick=timeGetTime();
}
//更新屏幕
_UpdateScreen(lpDDSTemp);
//自动跳桢
i=(newtick-oldtick)/time;
alpha=i*2+2;
if( i >= 15 ) //结束
{
alpha=31;
for(int j=0; j<ScreenWidth*ScreenHeight; j++)
{
lpBack[j]=Alpha_Pixel(lpDest[j], lpSour[j], alpha);
}
_UpdateScreen(lpDDSTemp);
break;
}
}
}
//--------------------------------------------------------------//
//////////////////////////////////////////////////////////////////
//--------------------------------------------------------------//
//残像淡入(suf:目标页面,step:残像的多少,time:延时 20左右)
void ScreenIn(int Step,int Time)
{
long T1=0, T2=0;
int tmp=ScreenHeight/Step;
WORD *Dest;
T1=T2=timeGetTime();
//取页面指针
if( BeginDraw(lpDDSBack) )
{
Dest=(WORD *)GraphBuffer;
EndDraw(lpDDSBack);
}
for( int j=0; j<tmp; j++)
{
//延时
while( T1-T2<Time )
{
T1=timeGetTime();
}
T2=T1;
for(int i=0; i<Step; i++)
memset(&Dest[ScreenWidth*i*tmp+ScreenWidth*j], 0, ScreenWidth*2);
_UpdateScreen(); //更新屏幕
}
}
//残像淡出(开始页面,目标页面,残像数,延时)
void ScreenOut(LPDIRECTDRAWSURFACE dest,int Step,int Time)
{
long T1, T2;
WORD *Dest,*Sour;
T1=T2=timeGetTime();
//临时页面
LPDIRECTDRAWSURFACE lpDDSTemp;
CreateBitmap(lpDDSTemp, ScreenWidth, ScreenHeight);
if( WindowMode != 0 ) //窗口
{
Blt(lpDDSTemp, 0,0, dest, RectScreen, false);
Blt(lpDDSBack, 0,0, lpDDSPrimary, RectWindow, false);
}
else
{
Blt(lpDDSTemp, 0,0, dest, RectScreen, false);
Blt(lpDDSBack, 0,0, lpDDSPrimary, RectScreen, false);
}
//取目标页面指针
if( BeginDraw(lpDDSBack) )
{
Sour=(WORD *)GraphBuffer;
EndDraw(lpDDSBack);
}
//取目标页面指针
if( BeginDraw(lpDDSTemp) )
{
Dest=(WORD *)GraphBuffer;
EndDraw(lpDDSTemp);
}
for( int j=0; j<ScreenHeight/Step; j++)
{
//延时
while( T1-T2<Time )
{
T1=timeGetTime();
}
T2=T1;
for(int i=0; i<Step; i++)
{
int sult=ScreenWidth*i*(ScreenHeight/Step)+ScreenWidth*j;
memcpy( &Sour[sult], &Dest[sult], ScreenWidth*2);
}
_UpdateScreen(); //更新屏幕
}
//释放
_RELEASE( lpDDSTemp );
}
//--------------------------------------------------------------//
//////////////////////////////////////////////////////////////////
//--------------------------------------------------------------//
//把一个表面顺时针旋转90度(本函数仅限于正方型矩阵)
void RolSurface(LPDIRECTDRAWSURFACE SS,int w)
{
WORD *Surf,*Temp;
int Width;
LPDIRECTDRAWSURFACE DS;
//取页面指针
if( BeginDraw(SS) )
{
Surf=(WORD *)GraphBuffer;
Width=GraphPitch;
EndDraw(SS);
}
CreateBitmap(DS, w, w, NULL, DDSCAPS_SYSTEMMEMORY);
//取页面指针
if( BeginDraw(DS) )
{
Temp=(WORD *)GraphBuffer;
EndDraw(DS);
}
_asm{
mov edi, Temp //指针保存到esi和edi中
mov esi, Surf
mov ebx, 0 //两个循环变量i,j
_loop1: mov ecx, 0
_loop2: mov eax, Width //eax放的是要翻转的表面的跨度
mul ebx //i*Width+j
add eax, ecx
shl eax, 1 //乘2
push eax //压栈:(i*Width+j)*2
mov eax, w //正方行的边长
dec eax //减一
sub eax, ecx //减j
mul Width //乘上跨度
add eax, ebx //加上i
shl eax, 1 //eax=((w-1-j)*Width+i)*2
mov dx, [esi+eax] //dx放的是当前点的位置
pop eax //恢复eax的值,eax = (i*Width+j)*2
mov [edi+eax], dx //放到新表面的相应点
inc ecx //j++
cmp ecx, w //j<w吗?
jnz _loop2 //还没有就还是在第二层循环
inc ebx //否则,i++
cmp ebx, w //i<w吗?
jnz _loop1 //还没有就继续循环
}
memcpy(Surf, Temp, (Width*w)*2); //把temp复制到surf上
//free(Temp);
}
//下面三个inline函数得到R,G,B的值
inline unsigned char GetRed(WORD color)
{
if( Is555 )
return (color>>7) & 0xff;
else
return (color>>8) & 0xff;
}
inline unsigned char GetGreen(WORD color)
{
if( Is555 )
return (color>>2) & 0xff;
else
return (color>>3) & 0xff;
}
inline unsigned char GetBlue(WORD color)
{
return (color & 0x1f) << 3;
}
// 功能:将一个16位的DirectDraw表面,存为一张24位BMP位图
// 输入:表面指针,输出的文件名
// 输出:是否成功
bool SaveToBitmapFile(LPDIRECTDRAWSURFACE lpSurface, char* filename)
{
WORD* lpBuffer; // 表面指针
int nPitch; // 表面跨距
int nWidth, nHeight; // 表面宽高
// 打开文件s
FILE* fp;
if( (fp=fopen(filename, "wb")) != NULL )
{
// 锁定表面
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
HRESULT ddrval = lpSurface->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
if( ddrval == DD_OK )
{
lpBuffer = (WORD *)ddsd.lpSurface;
nWidth = ddsd.dwWidth;
nHeight = ddsd.dwHeight;
//lPitch以Byte为单位计数的,GraphPitch以WORD为单位。所以GraphPitch = lPitch / 2;
nPitch = ddsd.lPitch >> 1;
}
// 保存文件头
BITMAPFILEHEADER FileHeader;
FileHeader.bfType = 'BM';
FileHeader.bfSize = nWidth * nHeight * 3 + 0x36;
FileHeader.bfReserved1 = 0;
FileHeader.bfReserved2 = 0;
FileHeader.bfOffBits = 0x36;
fwrite(&FileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
// 保存文件信息
BITMAPINFOHEADER Header;
Header.biSize = sizeof(BITMAPINFOHEADER); // 结构的大小
Header.biWidth = nWidth; // 宽
Header.biHeight = nHeight; // 高
Header.biPlanes = 1; // 固定
Header.biBitCount = 24; // 颜色数
Header.biCompression = BI_RGB; // 是否压缩
Header.biSizeImage = nWidth * nHeight * 3; // 图片的大小
Header.biXPelsPerMeter = 0;
Header.biYPelsPerMeter = 0;
Header.biClrUsed = 0;
Header.biClrImportant = 0;
fwrite(&Header, Header.biSize, 1, fp);
// 写入具体内容(从下向上存放)
fseek(fp, 0x36, SEEK_SET);
WORD word;
lpBuffer += nWidth * (nHeight - 1);
for(int i=0; i<nHeight; i++)
{
for(int j=0; j<nWidth; j++)
{
word = *lpBuffer;
fputc( GetBlue( word ), fp); // 蓝
fputc( GetGreen( word ), fp); // 绿
fputc( GetRed( word ), fp); // 红
lpBuffer++;
}
lpBuffer -= nPitch*2; // 指针转到上一行的开始
}
fclose(fp);
// 解锁表面
ddrval = lpSurface->Unlock( NULL );
return true;
}
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -