Nimbin[12]?SDL & Graphics / sdl_runtime_compiler / src/systems/word_anim_system.cpp

sdl_runtime_compiler git · main

SDL3 game for running and compiling code at runtime

sdl3 c++ compiler dlopen cmake · first commit 2026-04-19 · last commit 2026-07-03 (3 months ago) · synced 3 days ago · upstream: git.ide3.de/hsnr/sdl-runtime-compiler

C++ 72.3% C 26.2%
git clone https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler.gitwget https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler/archive/sdl_runtime_compiler.tar.gz
src/systems/word_anim_system.cpp 2.9 KB · 90 lines raw
#include <algorithm>

#include "entities/world.hpp"
#include "word_anim_system.hpp"
#include "utils/config.hpp"

namespace
Nimbin
{

static constexpr double ANIM_ADD_DUR   = 0.20;


static double smoothstep(double t)
{
    t = std::clamp(t, 0., 1.);
    return t * t * (3. - 2. * t);
}


static double lerp_d(double a, double b, double t) { return a + (b - a) * t; }


void
WordAnimSystem::update(DynArray<WordAnim_Add>&   anims_add,
                       DynArray<WordAnim_Drop>&  anims_drop,
                       CarriedLine&              carried,
                       DynArray<Text::TokenPtr>& words,
                       double                    dt)
{
    double floor_y = World::get_FloorY<double>();
    for (WordAnim_Add& anim : anims_add) {
        if (anim.complete) continue;

        anim.t += dt / ANIM_ADD_DUR;

        if (anim.t >= 1.0) {
            anim.complete    = true;
            anim.word->pos   = anim.target_pos;
            anim.word->yaw   = static_cast<float>(anim.yaw_target);
            anim.word->pitch = static_cast<float>(anim.pitch_target);
            carried.push(std::move(anim.word));
        }
        else {
            double s = smoothstep(anim.t);

            anim.word->pos = {
                lerp_d(anim.start_pos.x, anim.target_pos.x, s),
                lerp_d(anim.start_pos.y, anim.target_pos.y, s),
                lerp_d(anim.start_pos.z, anim.target_pos.z, s)
            };
            anim.word->yaw   = static_cast<float>(lerp_d(anim.yaw_start,   anim.yaw_target,   s));
            anim.word->pitch = static_cast<float>(lerp_d(anim.pitch_start, anim.pitch_target, s));
        }
    }

    anims_add.erase(
        std::remove_if(anims_add.begin(), anims_add.end(),
            [](const WordAnim_Add& a) { return a.complete; }),
        anims_add.end());

    for (WordAnim_Drop& drop : anims_drop) {
        if (drop.complete) continue;

        drop.word->body.vel.y -= Config::Physics::proj_grav * dt;
        drop.word->pos.x += drop.word->body.vel.x * dt;
        drop.word->pos.y += drop.word->body.vel.y * dt;
        drop.word->pos.z += drop.word->body.vel.z * dt;

        const double bottom = drop.word->pos.y - drop.word->shape.half_extents.y;
        if (bottom <= floor_y) {
            drop.complete          = true;
            drop.word->pos.y       = floor_y + drop.word->shape.half_extents.y;
            drop.word->body.vel.x *= 0.1;
            drop.word->body.vel.z *= 0.1;
            drop.word->body.vel.y  = 0.0;
            drop.word->body.mode   = PhysicsMode::Dynamic;
            if (drop.word->type == ObjectType::Text)
                drop.word->set_Look(Config::Color::keep, Text::Token::depth_floor);
            words.push_back(std::move(drop.word));
        }
    }

    anims_drop.erase(
        std::remove_if(anims_drop.begin(), anims_drop.end(),
            [](const WordAnim_Drop& d) { return d.complete; }),
        anims_drop.end());
}

} // namespace Nimbin