水波纹特效的C++模拟

简单的水波纹特效
Wave-GitHub
水波纹

#include "WaterWaveEngine.h"

int APIENTRY WinMain(HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR     lpCmdLine,
					 int       nCmdShow)
{
	IMAGE Buffer_In;
	loadimage(&Buffer_In, L"IMAGE", L"BackgroundImage");

	initgraph(Buffer_In.getwidth(), Buffer_In.getheight());

	WaterWaveEngine Wave(&Buffer_In, nullptr);//将In作为输入,程序窗口作为输出

	BeginBatchDraw();
	for(;;)
	{
		//处理鼠标操作,投石头
		while (MouseHit())
		{
			MOUSEMSG Msg = GetMouseMsg();
			//滑动水波与点击水波分开
			if(Msg.uMsg==WM_LBUTTONDOWN)
				Wave.PushStone(Msg.x, Msg.y, 20, 700);
			else if(Msg.mkLButton)
				Wave.PushStone(Msg.x, Msg.y, 20, 50);
		}

		Wave.Updata();//更新数据

		FlushBatchDraw();
		Sleep(2);
	}
	EndBatchDraw();
	closegraph();
}

WaterWaveEngine.h

#pragma once
#ifndef WATERWAVEENGINE_H
#define WATERWAVEENGINE_H

#include <easyx.h>
class WaterWaveEngine
{
protected:
	IMAGE*IMG_IN;
	IMAGE*IMG_OUT;
	DWORD *Buffer_In;
	DWORD *Buffer_Out;
	short *WaveBuff1;
	short *WaveBuff2;
	int Width;
	int Height;

	// 计算下一次波幅
	void NextFrame()
	{
		for (int i = Width; i < Height*(Width - 1); ++i)
		{
			WaveBuff2[i] = ((WaveBuff1[i - Width] + WaveBuff1[i + Width] + WaveBuff1[i - 1] + WaveBuff1[i + 1]) >> 1) - WaveBuff2[i];
			WaveBuff2[i] -= WaveBuff2[i] >> 5;// 波能衰减
		}
		short *ptmp = WaveBuff1;
		WaveBuff1 = WaveBuff2;
		WaveBuff2 = ptmp;
	}
	// 渲染
	void Render(DWORD*Texture, DWORD*Target, short*AmplitudeList)
	{
		int Ptr = 0;
		short Amplitude;
		int TexX;
		int TexY;
		int TarX;
		int TarY;
		for (TarY = 0; TarY < Height; TarY++)
			for (TarX = 0; TarX < Width; TarX++)
			{
				// 获得波幅
				Amplitude = 1024 - AmplitudeList[Ptr];
				// 计算偏移
				TexX = (((TarX - (Width >> 1)) * Amplitude) >> 10) + (Width >> 1);
				TexY = (((TarY - (Height >> 1)) * Amplitude) >> 10) + (Height >> 1);
				// 边界处理
				if (TexX >= Width)		TexX = Width - 1;
				if (TexX < 0)			TexX = 0;
				if (TexY >= Height)		TexY = Height - 1;
				if (TexY < 0)			TexY = 0;
				// 偏移 
				Target[TarX + TarY * Width] = Texture[TexX + (TexY * Width)];
				Ptr++;
			}
	}

public:
	// 更新数据
	IMAGE&Updata()
	{
		NextFrame();				//计算波幅
		Render(Buffer_In, Buffer_Out, WaveBuff1);	//渲染图片
		return *IMG_OUT;
	}
	// 获得FPS
	static double GetFPS()
	{
		const int FPS_COUNT = 8;
		static int i = 0;
		static DWORD LastTime = GetTickCount();
		static double fps;

		if (i > FPS_COUNT)
		{
			i = 0;
			int CurrentTime = GetTickCount();
			int PastTime = CurrentTime - LastTime;
			fps = FPS_COUNT / (PastTime / 1000.0f);
			LastTime = CurrentTime;
		}
		i++;
		return fps;
	}
	// 投石头
	void PushStone(int x, int y, int size, int weight)
	{
		// 突破边界不处理
		if ((x >= (int)Width - size) ||
			(x < size) ||
			(y >= (int)Height - size) ||
			(y < size))
			return;
		for (int posx = x - size; posx < x + size; posx++)
			for (int posy = y - size; posy < y + size; posy++)
				if ((posx - x)*(posx - x) + (posy - y)*(posy - y) < size*size)
					WaveBuff1[Width*posy + posx] += weight;
	}
	
	WaterWaveEngine() = delete;		// 删除默认构造函数
	// 使用引用或指针构造
	WaterWaveEngine(IMAGE&img_in, IMAGE&img_out) :
		IMG_IN(&img_in),
		IMG_OUT(&img_out)
	{
		Width = IMG_IN->getwidth();
		Height = IMG_IN->getheight();
		WaveBuff1 = new short[Width*Height]();
		WaveBuff2 = new short[Width*Height]();
		Resize(IMG_OUT, Width, Height);
		Buffer_In = GetImageBuffer(IMG_IN);
		Buffer_Out = GetImageBuffer(IMG_OUT);

	}
	WaterWaveEngine(IMAGE*pimg_in, IMAGE*pimg_out) :
		IMG_IN(pimg_in),
		IMG_OUT(pimg_out)
	{
		Width = IMG_IN->getwidth();
		Height = IMG_IN->getheight();
		WaveBuff1 = new short[Width*Height]();
		WaveBuff2 = new short[Width*Height]();
		Resize(IMG_OUT, Width, Height);
		Buffer_In = GetImageBuffer(IMG_IN);
		Buffer_Out = GetImageBuffer(IMG_OUT);
	}

	//重新绑定图片
	void Bind(IMAGE&img_in, IMAGE&img_out)
	{
		IMG_IN = &img_in;
		IMG_OUT = &img_out;
		Width = IMG_IN->getwidth();
		Height = IMG_IN->getheight();
		delete[]WaveBuff1;
		delete[]WaveBuff2;
		WaveBuff1 = new short[Width*Height]();
		WaveBuff2 = new short[Width*Height]();
		Resize(IMG_OUT, Width, Height);
		Buffer_In = GetImageBuffer(IMG_IN);
		Buffer_Out = GetImageBuffer(IMG_OUT);
	}
	void Bind(IMAGE*pimg_in, IMAGE*pimg_out)
	{
		IMG_IN = pimg_in;
		IMG_OUT = pimg_out;
		Width = IMG_IN->getwidth();
		Height = IMG_IN->getheight();
		delete[]WaveBuff1;
		delete[]WaveBuff2;
		WaveBuff1 = new short[Width*Height]();
		WaveBuff2 = new short[Width*Height]();
		Resize(IMG_OUT, Width, Height);
		Buffer_In = GetImageBuffer(IMG_IN);
		Buffer_Out = GetImageBuffer(IMG_OUT);
	}
	virtual ~WaterWaveEngine()
	{
		delete[]WaveBuff1;
		delete[]WaveBuff2;
	}
};
#endif // !WATERWAVEENGINE_H
原文地址:https://www.cnblogs.com/that-boy/p/12310365.html