OpenSiv3D icon indicating copy to clipboard operation
OpenSiv3D copied to clipboard

SmoothDamp を簡単に扱える Smooth<Type> クラス

Open Reputeless opened this issue 2 years ago • 0 comments

# include <Siv3D.hpp> // OpenSiv3D v0.6.6

template <class Type>
struct Smooth
{
public:

	using value_type = Type;

	SIV3D_NODISCARD_CXX20
	Smooth() = default;

	SIV3D_NODISCARD_CXX20
	constexpr Smooth(const value_type& value) noexcept
		: m_value{ value }
		, m_target{ value } {}

	template <class... Args, std::enable_if_t<std::is_constructible_v<Type, Args...>>* = nullptr>
	SIV3D_NODISCARD_CXX20
	constexpr Smooth(Args&&... args) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
		: m_value{ std::forward<Args>(args)... }
		, m_target{ m_value } {}

	Smooth& operator= (const Smooth&) = default;

	constexpr Smooth& operator= (const value_type& value) noexcept
	{
		return set(value);
	}

	constexpr Smooth& set(const value_type& value, const value_type& velocity = value_type{}) noexcept
	{
		m_value = value;

		m_target = value;

		m_velocity = velocity;

		return *this;
	}

	constexpr Smooth& setTarget(const value_type& target) noexcept
	{
		m_target = target;

		return *this;
	}

	const Type& update(const Duration& smoothTime, const Optional<double>& maxSpeed = unspecified, double deltaTime = Scene::DeltaTime()) noexcept
	{
		return (m_value = Math::SmoothDamp(m_value, m_target, m_velocity, smoothTime.count(), maxSpeed, deltaTime));
	}

	const Type& update(double smoothTime, const Optional<double>& maxSpeed = unspecified, double deltaTime = Scene::DeltaTime()) noexcept
	{
		return (m_value = Math::SmoothDamp(m_value, m_target, m_velocity, smoothTime, maxSpeed, deltaTime));
	}

	[[nodiscard]]
	constexpr const value_type& value() const noexcept
	{
		return m_value;
	}

	[[nodiscard]]
	constexpr const value_type& target() const noexcept
	{
		return m_target;
	}

	[[nodiscard]]
	constexpr const value_type& velocity() const noexcept
	{
		return m_velocity;
	}

private:

	value_type m_value{};

	value_type m_target{};

	value_type m_velocity{};
};

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	Smooth<Vec2> pos = Scene::Center();

	Smooth<double> value = 0.0;

	while (System::Update())
	{
		pos.update(0.2s);

		value.update(0.1s);

		Circle{ pos.value(), 40 }.draw(ColorF{ 1, 0, 0, 0.5 });

		Circle{ value.value(), 0, 15 }.draw(ColorF{ 0.5 });

		PutText(U"{:.2f}"_fmt(value.value()), Vec2{ value.value(), 30 });

		if (MouseL.down())
		{
			pos.setTarget(Cursor::Pos());

			value.setTarget(Random(0, 800));
		}
	}
}

ToDo

  • [ ] ColorF 対応

Reputeless avatar Jan 27 '23 04:01 Reputeless