Polygonの形状に沿って軌跡を描く
https://scrapbox.io/files/64e4c4cdc79a2d001bfe806e.mp4
code:siv_trail_polygon_highlight.cpp
# include <Siv3D.hpp> // OpenSiv3D v0.6.11
struct PolygonHighlightEffect : IEffect
{
Array<TrailMotion> trails;
Polygon polygon;
PolygonHighlightEffect(const Polygon& targetPolygon)
: polygon{ targetPolygon }
{
constexpr std::array<ColorF, 3> colors = { Palette::White, Palette::Magenta, Palette::Cyan };
for (int iTrail : step(3))
{
trails << TrailMotion{}
.setLifeTime(DisplayTime + 0.5 * iTrail)
.setColor(ColorF{ colorsiTrail, 1 - 0.2 * iTrail }) .setSizeFunction(=(double timeSec) { const double size = 2 + 3 * iTrail;
const double sizeScale1 = timeSec < LifeTime ? 1 : 0;
const double sizeScale2 = timeSec < 0.1 ? timeSec / 0.1 : 1;
const double displayTimeScaled = DisplayTime * 0.7;
const double sizeScale3 = timeSec < displayTimeScaled ? 1 : EaseInExpo(1 - ((timeSec - displayTimeScaled) / (LifeTime - displayTimeScaled)));
return size * sizeScale1 * sizeScale2 * sizeScale3;
})
.setPositionFunction(&(double timeSec) { const double t = Min(timeSec, DisplayTime);
const double t0_1 = t / (DisplayTime * 0.8);
const auto& vertices = polygon.outer();
const int index1 = ((int)(t0_1 * vertices.size())) % vertices.size();
const int index2 = (index1 + 1) % vertices.size();
double tmp;
const double lerpFactor = modf(t0_1 * vertices.size(), &tmp);
const auto v = verticesindex1.lerp(verticesindex2, EaseInExpo(lerpFactor)); return v;
});
}
}
bool update(double timeSec) override
{
for (auto& trail : trails)
{
trail.update();
}
{
const ScopedRenderStates2D blend{ BlendState::Additive };
for (const auto& trail : trails)
{
trail.draw();
}
}
return timeSec < 3.0;
}
private:
inline static constexpr double DisplayTime = 0.3;
inline static constexpr double LifeTime = 1.0;
};
void Main()
{
Scene::SetBackground(ColorF{ 0 });
const RectF rect{ Arg::center = Scene::CenterF().movedBy(-160, -140), SizeF{ 200, 180 }};
const Circle circle{ Scene::CenterF().movedBy(160, 140), 100 };
const Polygon star = Shape2D::Star(128, Scene::CenterF().movedBy(-160, 140));
const Polygon nstar = Shape2D::NStar(12, 128, 96, Scene::CenterF().movedBy(160, -140));
Effect effect;
while (System::Update())
{
rect.drawFrame(1, 0, Palette::Silver);
circle.drawFrame(1, 0, Palette::Silver);
star.drawFrame(1, Palette::Silver);
nstar.drawFrame(1, Palette::Silver);
if (rect.leftClicked())
{
effect.add<PolygonHighlightEffect>(rect.asPolygon());
}
else if (circle.leftClicked())
{
effect.add<PolygonHighlightEffect>(circle.asPolygon());
}
else if (star.leftClicked())
{
effect.add<PolygonHighlightEffect>(star);
}
else if (nstar.leftClicked())
{
effect.add<PolygonHighlightEffect>(nstar);
}
else if (Scene::Rect().leftClicked())
{
effect.add<PolygonHighlightEffect>(Scene::Rect().stretched(-1).asPolygon());
}
effect.update();
}
}