跳转至

05-通用定时器与摄像机特效

我们需要一个定时器来控制抖动特效开始和结束的时刻。
往长远一点来看,游戏中很多内容都与时间息息相关。
因此我们实现一个通用定时器类Timer,来对时间进行统一管理。

1 通用定时器Timer类

Timer的实现有两种思路,分别是“继承”和“回调”
Pasted image 20260301123756.png
通过比较可以意识到,使用“回调”更加简介,不需要像继承那样定义多个子类。

class Timer
{
public:
    Timer() = default;
    ~Timer() = default;

    void restart()
    {
        pass_time = 0;
        shotted = false;
    }

    void set_wait_time(int val)
    {
        wait_time = val;
    }

    void set_one_shot(bool flag)
    {
        one_shot = flag;
    }

    void set_callback(std::function<void()> callback)
    {
        this->callback = callback;
    }

    void pause()
    {
        paused = true;
    }

    void resume()
    {
        paused = false;
    }

    void on_update(int delta)
    {
        if(paused)
            return;

        pass_time += delta;
        if(pass_time >= wait_time)
        {
            if((!one_shot || one_shot && !shotted) && callback) {
                callback();
            }
            shotted = true;
            pass_time = 0;
        }
    }

protected:
    std::function<void()> callback;     //触发回调
    int pass_time = 0;      //已过时间
    int wait_time = 0;      //等待时间
    bool paused = false;    //是否暂停
    bool shotted = false;   //是否触发
    bool one_shot = false;  //单次触发
};

之后我们对Timer进行测试
在MenuScene的on_enter()设置timer
timer.set_wait_time(1000);
timer.set_one_shot(false);
timer.set_callback(
    []()
    {
        std::cout << "Shot!" << std::endl;
    }
);

在on_update()对timer进行更新
timer.on_update(delta);

2 摄像机抖动特效

摄像机抖动可以使用随机数生成或者噪声函数。这里为了简单起见,我们使用随机数生成来实现。

Timer timer_shake;              //摄像机抖动定时器
bool is_shaking = false;        //摄像机是否正在抖动
float shaking_strength = 0;     //摄像机抖动幅度

在Camera的初始化中对定时器进行设置
timer_shake.set_one_shot(true);
timer_shake.set_callback(
    [&](){ 
        is_shaking = false;
        reset(); 
    }
);

编写shake函数
void shake(float strength, int duration)
{
    is_shaking = true;
    shaking_strength = strength;

    timer_shake.set_wait_time(duration);
    timer_shake.restart();
}

在on_update中编写抖动逻辑
void on_update(int delta)
{
    timer_shake.on_update(delta);

    if(is_shaking)
    {
        position.x = (-50 + rand() % 100) / 50.0f * shaking_strength;
        position.y = (-50 + rand() % 100) / 50.0f * shaking_strength;
    }
}

之后在MenuScene的on_input()中再按下任意键时调用shake
void on_input(const ExMessage& msg) { 
    if(msg.message == WM_KEYDOWN)
    {
        camera.shake(10, 350);
    }
}

评论

如果你已登录 GitHub,就可以直接在这里评论。