11class HanachanChainManager {
13 HanachanChainManager(
const std::span<const f32> &linkDistances);
14 ~HanachanChainManager();
18 for (
auto &link : m_links) {
27 ASSERT(idx < m_links.size());
28 m_links[idx].setPos(pos);
33 ASSERT(idx < m_links.size());
34 m_links[idx].setVel(v);
39 ASSERT(idx < m_links.size());
40 return m_links[idx].pos();
45 ASSERT(idx < m_links.size());
46 return m_links[idx].up();
51 ASSERT(idx < m_links.size());
52 m_links[idx].addSpringForce(v);
57 void calcConstraints() {
58 for (
size_t i = 1; i < m_links.size(); ++i) {
59 m_links[i].calcConstraints(1.0f);
66class ObjectHanachanPart :
public ObjectCollidable {
67 friend class ObjectHanachan;
74 : ObjectCollidable(name, pos, rot, scale) {}
77 ~ObjectHanachanPart() =
default;
85 [[nodiscard]]
const char *getKclName()
const override {
90 void loadRail()
override {}
94 void calcTransformFromUpAndTangent(
const EGG::Vector3f &pos,
const EGG::Vector3f &up,
95 const EGG::Vector3f &tangent) {
97 SetRotTangentHorizontal(mat, up, tangent);
150class ObjectHanachan final :
public ObjectCollidable,
public StateManager {
153 ~ObjectHanachan()
override;
155 void init()
override;
158 void calc()
override {
160 StateManager::calc();
170 void loadGraphics()
override {}
173 void createCollision()
override {}
176 enum class RailAlignment {
200 void calcSlowMotion() {
201 constexpr f32 PERIOD = 50.0f;
202 constexpr f32 WAVELENGTH = 4000.0f;
204 calcLateralMotion(
m_stillAngVel, PERIOD, WAVELENGTH, m_currentFrame);
208 void calcFastMotion(s32 frame) {
209 constexpr f32 AMPLITUDE = 25.0f;
210 constexpr f32 PERIOD = 300.0f;
211 constexpr f32 WAVELENGTH = 5500.0f;
213 calcLateralMotion(AMPLITUDE, PERIOD, WAVELENGTH,
static_cast<s16
>(frame));
216 void calcLateralMotion(f32 amplitude, f32 period, f32 wavelength, s16 frame);
217 [[nodiscard]] RailAlignment calcRailAlignment()
const;
220 [[nodiscard]]
bool shouldStartMoving()
const {
221 return m_currentFrame > m_stillDuration;
225 void setMovingVel() {
226 m_railInterpolator->setCurrVel(m_movingVel);
229 [[nodiscard]] ObjectHanachanHead *&headPart() {
230 return reinterpret_cast<ObjectHanachanHead *&
>(m_parts[0]);
233 [[nodiscard]] std::span<ObjectHanachanPart *> bodyParts() {
234 return std::span(m_parts.begin() + 1, m_parts.size() - 1);
237 std::array<ObjectHanachanPart *, 7> m_parts;
238 HanachanChainManager m_chain;
239 const f32 m_movingVel;
247 RailAlignment m_prevRailAlignment;
259 static constexpr std::array<StateManagerEntry, 2> STATE_ENTRIES = {{
260 {StateEntry<ObjectHanachan, &ObjectHanachan::initWalk, &ObjectHanachan::calcWalk>(0)},
261 {StateEntry<ObjectHanachan, &ObjectHanachan::initWait, &ObjectHanachan::calcWait>(1)},