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

猜你喜欢

转载自www.cnblogs.com/that-boy/p/12310365.html