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

📄 ripple.cpp

📁 《Visual C/C++图形图像与游戏编程典型实例解析》配套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    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 = BACKWIDTH;
    ddsd.dwHeight = BACKHEIGHT;

    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, ChooseWnd());
	lpDDSPrimary->SetClipper(lpClipper);

	if( !InitSurfaces() )
        return FALSE;

    return TRUE;
}

//******************************************************************
//函数:WinMain()
//功能:应用程序入口
//******************************************************************
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine, int nCmdShow)
{
    MSG         msg;
	hInst=hInstance;

	ShowAbout();
	//初始化主窗口
	if ( !InitWindow( hInstance, nCmdShow ) )
		return FALSE;

	//初始化DirectDraw环境
	if ( !InitDDraw())
	{
		MessageBox(fullscreen ? hwndwin:hwndful, "初始化DirectDraw过程中出错!", "Error", MB_OK );
		FreeObjects();
		return FALSE;
	}

	//进入消息循环
	while(1)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if(!GetMessage(&msg, NULL, 0, 0 )) return msg.wParam;
			TranslateMessage(&msg); 
			DispatchMessage(&msg);
		}
		else if(bActive)
		{
			UpdateFrame();
		}
		else WaitMessage();
	}
    return msg.wParam;
} 

//******************************************************************
//函数:InitSurfaces()
//功能:初始化页面图象
//******************************************************************
BOOL InitSurfaces( void )
{
    DDReLoadBitmap(lpDDSPic1, "back.bmp");

    buf1 = new short[BACKWIDTH*BACKHEIGHT];
	buf2 = new short[BACKWIDTH*BACKHEIGHT];
	ZeroMemory(buf1, BACKWIDTH*BACKHEIGHT*sizeof(short));
	ZeroMemory(buf2, BACKWIDTH*BACKHEIGHT*sizeof(short));

	for (int i=0; i<10; i++)
		DropStone(BACKWIDTH*i/10, BACKHEIGHT/2, 3, 128);

    return TRUE;
}

//*******************************************************
//计算波能数据缓冲区
//*******************************************************
void RippleSpread()
{
	for (int i=BACKWIDTH; i<BACKWIDTH*BACKHEIGHT-BACKWIDTH; i++)
	{
		//波能扩散
		buf2[i] = ((buf1[i-1]+
					buf1[i+1]+
					buf1[i-BACKWIDTH]+
					buf1[i+BACKWIDTH])
					>>1)
					- buf2[i];
		//波能衰减
		buf2[i] -= buf2[i]>>5;
	}

	//交换波能数据缓冲区
	short *ptmp =buf1;
	buf1 = buf2;
	buf2 = ptmp;
}

//*******************************************************
//根据波能数据缓冲区对离屏页面进行渲染
//*******************************************************
void 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 = BACKWIDTH;
	for (int i=1; i<BACKHEIGHT-1; i++)
	{
		for (int j=0; j<BACKWIDTH; j++)
		{
			//计算偏移量
			xoff = buf1[k-1]-buf1[k+1];
			yoff = buf1[k-BACKWIDTH]-buf1[k+BACKWIDTH];

			//判断坐标是否在窗口范围内
			if ((i+yoff )< 0 ) {k++; continue;}
			if ((i+yoff )> BACKHEIGHT) {k++; continue;}
			if ((j+xoff )< 0 ) {k++; continue;}
			if ((j+xoff )> BACKWIDTH ) {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);
}

//********************************************************
//更新屏幕
//********************************************************
void UpdateFrame( void )
{
	//随机增加波源
	if (rain==TRUE)
	DropStone(
			(int)(BACKWIDTH*((short)rand()/32767.0)),
			(int)(BACKHEIGHT*((short)rand()/32767.0)),
			3,
			128
			);
	if (downripper==TRUE)
	DropStone(
			(int)(BACKWIDTH*((short)rand()/32767.0)),
			BACKHEIGHT-3,
			3,
			128
			);
	if (upripper==TRUE)
	DropStone(
			(int)(BACKWIDTH*((short)rand()/32767.0)),
			3,
			3,
			128
			);

	RippleSpread();//计算波能数据缓冲区
	RenderRipple();//页面渲染

	//将离屏页面图象Blit到主页面
	RECT Window;
	POINT pt;
	GetClientRect(ChooseWnd(), &Window);
	pt.x=pt.y=0;
	ClientToScreen(ChooseWnd(), &pt);
	OffsetRect(&Window, pt.x, pt.y);
	lpDDSPrimary->Blt(&Window, lpDDSPic2, NULL, DDBLT_WAIT, NULL);
}

void MakeRect(RECT *rect, short left, short top, short width, short height)
{
	rect->left=left;
	rect->top=top;
	rect->right=left+width;
	rect->bottom=top+height;
}

//*****************************************************
//增加波源
//*****************************************************
void DropStone(int x,//x坐标
			   int y,//y坐标
			   int stonesize,//波源半径
			   int stoneweight)//波源能量
{
	//判断坐标是否在屏幕范围内
	if ((x+stonesize)>BACKWIDTH || 
		(y+stonesize)>BACKHEIGHT||
		(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[BACKWIDTH*posy+posx] = -stoneweight;
}

void ShowAbout(void)
{
	char temp[]="\n"
		"===============水波特效================"
		"\n\n"
		"            天恒工作室  唐洁           \n"
		"\n\n"
		"  Email   : tj@ahpost.com.cn或flyingtjf@sina.com.cn\n"
		"\n\n"
		"             2004年12月9日\n\n"
		"=======================================\n\n"
		;
	
	MessageBox(ChooseWnd(), temp, TITLE, MB_OK);
}

HWND ChooseWnd()
{
	return fullscreen ? hwndful:hwndwin;
}

//调整窗口大小
void AdjustWindowSize(HWND hwnd)
{
	RECT rect;
	MakeRect(&rect, 0, 0, BACKWIDTH, BACKHEIGHT );
	AdjustWindowRectEx( &rect,
						GetWindowStyle(hwnd),
						GetMenu(hwnd)!=NULL,
						GetWindowExStyle(hwnd));
	MoveWindow( hwnd,
		(GetSystemMetrics(SM_CXFULLSCREEN)-(rect.right-rect.left))/2,
		(GetSystemMetrics(SM_CYFULLSCREEN)-(rect.bottom-rect.top))/2,
		rect.right-rect.left,
		rect.bottom-rect.top,
		TRUE);
}

//初始化预览窗口
BOOL InitPreviewWindow( HINSTANCE hInstance, int nCmdShow )
{
    WNDCLASS	wc3;	//窗口类结构

	//填充窗口类结构
    wc3.style = 0;
    wc3.lpfnWndProc = WinProc;
    wc3.cbClsExtra = 0;
    wc3.cbWndExtra = 0;
    wc3.hInstance = hInstance;
    wc3.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(ID_APP)); 
    wc3.hCursor = LoadCursor( NULL, IDC_ARROW);
    wc3.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc3.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
	wc3.lpszClassName = "preview";

	//注册窗口类
    RegisterClass( &wc3 );
    
	//创建窗口
	HWND tmp=CreateWindowEx(
		0,
		"preview",
		"水波预览",	//窗口的标题名
		WS_OVERLAPPEDWINDOW,
		0,0,
		10,10,
		NULL,
		NULL,
		hInstance,
		NULL );

	if (!tmp) return FALSE;

	ShowWindow(tmp, SW_HIDE);
	UpdateWindow(tmp);

	return TRUE;
}

⌨️ 快捷键说明

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