简单的水波纹特效
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