📄 ripplewnd.cpp
字号:
//NetTalk
/*------------------------------------------------------------------------------*\
=============================
模块名称: RippleWnd.cpp
=============================
[版权]
\*------------------------------------------------------------------------------*/
//借鉴来的水波特效,作者不详,在此谢过
#include "WndX.h"
#include "RippleWnd.h"
#include <Stdio.h>
#include <Windowsx.h>
#pragma comment(lib,"ddraw")
/*------------------------------------------------------------------------------*/
CRippleWnd::CRippleWnd()
{
m_iCount=0;
m_dwFps=0;
}
/*------------------------------------------------------------------------------*/
CRippleWnd::~CRippleWnd()
{
}
/*------------------------------------------------------------------------------*/
BOOL CRippleWnd::Create(RECT &rc, HWND hParent,UINT uBmpID,int iWidth,int iHeight)
{
BOOL bRet=FALSE;
m_iWidth=iWidth;
m_iHeight=iHeight;
if(!CWndX::Create(0,0,0,WS_CHILD|WS_VISIBLE,rc,hParent,0,0))
goto RET;
SetClassLong(m_hWnd,GCL_HBRBACKGROUND,0);
if(!InitDDraw(uBmpID,iWidth,iHeight))
goto RET;
SetTimer(m_hWnd,1,30,0);
m_dwTime=GetTickCount();
bRet=TRUE;
RET:
return bRet;
}
/*------------------------------------------------------------------------------*/
LRESULT CRippleWnd::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
KillTimer(m_hWnd,1);
FreeObject();
break;
case WM_TIMER:
{
if(IsWindowVisible(m_hWnd))
{
UpdateFrame();
}
}
break;
case WM_LBUTTONDOWN:
DropStone(LOWORD(lParam),HIWORD(lParam),3,128);
break;
case WM_MOUSEMOVE:
if (wParam==MK_LBUTTON )
{
DropStone(LOWORD(lParam),HIWORD(lParam),3,128);
}
break;
}
return CWndX::WndProc(uMsg,wParam,lParam);
}
/*------------------------------------------------------------------------------*/
BOOL CRippleWnd::InitDDraw(UINT uBmpID,int iWidth,int iHeight)
{
DDSURFACEDESC ddsd;
HRESULT ddrval;
//创建DirectDraw对象
ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
if( ddrval != DD_OK )
return FALSE;
ddrval = lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
if( ddrval != DD_OK )
return FALSE;
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS ;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
if( ddrval != DD_OK )
return FALSE;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |DDSCAPS_SYSTEMMEMORY ;
ddsd.dwWidth = iWidth;
ddsd.dwHeight = iHeight;
if (lpDD->CreateSurface(&ddsd, &lpDDSPic1, NULL) != DD_OK)
return FALSE;
if (lpDD->CreateSurface(&ddsd, &lpDDSPic2, NULL) != DD_OK)
return FALSE;
lpDD->CreateClipper(0, &lpClipper, NULL);
lpClipper->SetHWnd(0, m_hWnd);
lpDDSPrimary->SetClipper(lpClipper);
DDReLoadBitmap(lpDDSPic1, MAKEINTRESOURCE(uBmpID));
buf1 = new short[iWidth*iHeight];
buf2 = new short[iWidth*iHeight];
ZeroMemory(buf1, iWidth*iHeight*sizeof(short));
ZeroMemory(buf2, iWidth*iHeight*sizeof(short));
return TRUE;
}
/*------------------------------------------------------------------------------*/
void CRippleWnd::FreeObject()
{
if( lpDD != NULL )//释放DirectDraw对象
{
if( lpDDSPrimary != NULL )//释放主页面。
{
lpDDSPrimary->Release();
lpDDSPrimary = NULL;
}
if( lpDDSPic1 != NULL )//释放离屏页面。
{
lpDDSPic1->Release();
lpDDSPic1 = NULL;
}
if( lpDDSPic2 != NULL )
{
lpDDSPic2->Release();
lpDDSPic2 = NULL;
}
if (lpClipper!=NULL)
{
lpClipper->Release();
lpClipper=NULL;
}
lpDD->Release();
lpDD = NULL;
}
if(buf1)
delete buf1;
if(buf2)
delete buf2;
}
/*------------------------------------------------------------------------------*/
void CRippleWnd::DropStone(int x,int y,int stonesize,int stoneweight)
{
//判断坐标是否在屏幕范围内
if ((x+stonesize)>m_iWidth ||
(y+stonesize)>m_iHeight||
(x-stonesize)<0||
(y-stonesize)<0)
return;
for (int posx=x-stonesize; posx<x+stonesize; posx++)
for (int posy=y-stonesize; posy<y+stonesize; posy++)
if ((posx-x)*(posx-x) + (posy-y)*(posy-y) < stonesize*stonesize)
buf1[m_iWidth*posy+posx] = -stoneweight;
}
/*------------------------------------------------------------------------------*/
void CRippleWnd::RenderRipple()
{
//锁定两个离屏页面
DDSURFACEDESC ddsd1, ddsd2;
ddsd1.dwSize = sizeof (DDSURFACEDESC);
ddsd2.dwSize = sizeof(DDSURFACEDESC);
lpDDSPic1->Lock(NULL, &ddsd1, DDLOCK_WAIT, NULL);
lpDDSPic2->Lock(NULL, &ddsd2, DDLOCK_WAIT, NULL);
//取得页面象素位深度,和页面内存指针
int depth=ddsd1.ddpfPixelFormat.dwRGBBitCount/8;
BYTE *Bitmap1 = (BYTE*)ddsd1.lpSurface;
BYTE *Bitmap2 = (BYTE*)ddsd2.lpSurface;
//下面进行页面渲染
int xoff, yoff;
int k = m_iWidth;
for (int i=1; i<m_iHeight-1; i++)
{
for (int j=0; j<m_iWidth; j++)
{
//计算偏移量
xoff = buf1[k-1]-buf1[k+1];
yoff = buf1[k-m_iWidth]-buf1[k+m_iWidth];
//判断坐标是否在窗口范围内
if ((i+yoff )< 0 ) {k++; continue;}
if ((i+yoff )> m_iHeight) {k++; continue;}
if ((j+xoff )< 0 ) {k++; continue;}
if ((j+xoff )> m_iWidth ) {k++; continue;}
//计算出偏移象素和原始象素的内存地址偏移量
int pos1, pos2;
pos1=ddsd1.lPitch*(i+yoff)+ depth*(j+xoff);
pos2=ddsd2.lPitch*i+ depth*j;
//复制象素
for (int d=0; d<depth; d++)
Bitmap2[pos2++]=Bitmap1[pos1++];
k++;
}
}
//解锁页面
lpDDSPic1->Unlock(&ddsd1);
lpDDSPic2->Unlock(&ddsd2);
HDC hdc;
lpDDSPic2->GetDC(&hdc);
char szFps[10];
sprintf(szFps,"%dFPS",m_dwFps);
SetBkMode(hdc,TRANSPARENT);
SetTextColor(hdc,0x00ffaaaa);
DrawText(hdc,szFps,strlen(szFps),&CRectX(200,5,280,20),DT_RIGHT);
lpDDSPic2->ReleaseDC(hdc);
}
/*------------------------------------------------------------------------------*/
void CRippleWnd::UpdateFrame()
{
m_iCount++;
if(m_iCount>=20)
{
DropStone(
(int)(m_iWidth*((short)rand()/32767.0)),
(int)(m_iHeight*((short)rand()/32767.0)),
3,
128
);
DWORD temp=GetTickCount();
m_dwFps=20000/(temp-m_dwTime);
m_dwTime=temp;
m_iCount=0;
}
RippleSpread();
RenderRipple();//页面渲染
//将离屏页面图象Blit到主页面
RECT Window;
POINT pt;
GetClientRect(m_hWnd, &Window);
pt.x=pt.y=0;
ClientToScreen(m_hWnd, &pt);
OffsetRect(&Window, pt.x, pt.y);
lpDDSPrimary->Blt(&Window, lpDDSPic2, NULL, DDBLT_WAIT, NULL);
}
/*------------------------------------------------------------------------------*/
void CRippleWnd::RippleSpread()
{
for (int i=m_iWidth; i<m_iWidth*m_iHeight-m_iWidth; i++)
{
//波能扩散
buf2[i] = ((buf1[i-1]+
buf1[i+1]+
buf1[i-m_iWidth]+
buf1[i+m_iWidth])
>>1)
- buf2[i];
//波能衰减
buf2[i] -= buf2[i]>>5;
}
//交换波能数据缓冲区
short *ptmp =buf1;
buf1 = buf2;
buf2 = ptmp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -