feat(act): 改进动作系统的更新逻辑和功能
- 重构动作序列(Seq)的step方法,支持更精确的时间分割处理 - 为Spawn和Repeat动作添加step方法实现 - 改进RepeatForever的step方法,防止无限循环 - 为MoveTo/MoveBy动作添加标签复制功能 - 在Node类中暴露comps_成员给SceneGraph访问 - 修复测试用例中的动作调用方式 - 添加Vec2的乘法运算符重载
This commit is contained in:
parent
d1d03520ff
commit
6396a0b5d5
|
|
@ -32,6 +32,8 @@ protected:
|
|||
Node* target_ = nullptr;
|
||||
Node* origTarget_ = nullptr;
|
||||
i32 tag_ = -1;
|
||||
|
||||
void copyTagTo(Act* other) const { other->tag_ = tag_; }
|
||||
};
|
||||
|
||||
class ActInstant : public Act {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ public:
|
|||
|
||||
void start(Node* t) override;
|
||||
void stop() override;
|
||||
void step(f32 dt) override;
|
||||
void update(f32 t) override;
|
||||
Act* clone() const override;
|
||||
Act* reverse() const override;
|
||||
|
|
@ -72,6 +73,7 @@ public:
|
|||
bool done() const override;
|
||||
void start(Node* t) override;
|
||||
void stop() override;
|
||||
void step(f32 dt) override;
|
||||
void update(f32 t) override;
|
||||
Act* clone() const override;
|
||||
Act* reverse() const override;
|
||||
|
|
|
|||
|
|
@ -21,8 +21,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
Act* clone() const override { return new MoveTo(dur_, end_); }
|
||||
Act* reverse() const override { return new MoveTo(dur_, start_); }
|
||||
Act* clone() const override {
|
||||
auto* c = new MoveTo(dur_, end_);
|
||||
copyTagTo(c);
|
||||
return c;
|
||||
}
|
||||
Act* reverse() const override {
|
||||
auto* r = new MoveTo(dur_, start_);
|
||||
copyTagTo(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
private:
|
||||
Vec2 start_;
|
||||
|
|
@ -44,8 +52,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
Act* clone() const override { return new MoveBy(dur_, dlt_); }
|
||||
Act* reverse() const override { return new MoveBy(dur_, -dlt_); }
|
||||
Act* clone() const override {
|
||||
auto* c = new MoveBy(dur_, dlt_);
|
||||
copyTagTo(c);
|
||||
return c;
|
||||
}
|
||||
Act* reverse() const override {
|
||||
auto* r = new MoveBy(dur_, -dlt_);
|
||||
copyTagTo(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
private:
|
||||
Vec2 dlt_;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
void update(f32 t) override {
|
||||
if (target_) {
|
||||
target_->scale = start_ + dlt_ * t;
|
||||
target_->scale = start_ * Vec2::lerp(Vec2(1, 1), dlt_, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ struct Vec2 {
|
|||
Vec2 operator-(const Vec2 &v) const { return {x - v.x, y - v.y}; }
|
||||
Vec2 operator*(float s) const { return {x * s, y * s}; }
|
||||
Vec2 operator/(float s) const { return {x / s, y / s}; }
|
||||
Vec2 operator*(const Vec2 &v) const { return {x * v.x, y * v.y}; }
|
||||
Vec2 operator-() const { return {-x, -y}; }
|
||||
|
||||
Vec2 &operator+=(const Vec2 &v) {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ protected:
|
|||
};
|
||||
|
||||
class Node : public std::enable_shared_from_this<Node> {
|
||||
friend class SceneGraph;
|
||||
public:
|
||||
virtual ~Node();
|
||||
|
||||
|
|
@ -150,8 +151,6 @@ public:
|
|||
|
||||
protected:
|
||||
virtual Vec2 defaultAnchor() const { return Vec2(0.5f, 0.5f); }
|
||||
|
||||
private:
|
||||
std::vector<Unique<Comp>> comps_;
|
||||
Node* parent_ = nullptr;
|
||||
std::vector<Ref<Node>> children_;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ Seq* Seq::createFromArray(std::initializer_list<Act*> acts) {
|
|||
void Seq::start(Node* t) {
|
||||
ActInterval::start(t);
|
||||
curIdx_ = 0;
|
||||
split_ = 0.0f;
|
||||
if (!acts_.empty()) {
|
||||
acts_[0]->start(t);
|
||||
}
|
||||
|
|
@ -56,21 +57,31 @@ void Seq::step(f32 dt) {
|
|||
|
||||
elap_ += dt;
|
||||
|
||||
while (curIdx_ < acts_.size()) {
|
||||
f32 remainingDt = dt;
|
||||
|
||||
while (curIdx_ < acts_.size() && remainingDt > 0) {
|
||||
auto* cur = acts_[curIdx_];
|
||||
if (auto* interval = dynamic_cast<ActInterval*>(cur)) {
|
||||
interval->step(dt);
|
||||
if (!interval->done()) {
|
||||
return;
|
||||
f32 neededDt = interval->dur() - interval->elap();
|
||||
if (remainingDt >= neededDt) {
|
||||
interval->step(neededDt);
|
||||
remainingDt -= neededDt;
|
||||
cur->stop();
|
||||
curIdx_++;
|
||||
if (curIdx_ < acts_.size()) {
|
||||
acts_[curIdx_]->start(target_);
|
||||
}
|
||||
} else {
|
||||
interval->step(remainingDt);
|
||||
remainingDt = 0;
|
||||
}
|
||||
cur->stop();
|
||||
} else {
|
||||
cur->step(dt);
|
||||
}
|
||||
|
||||
curIdx_++;
|
||||
if (curIdx_ < acts_.size()) {
|
||||
acts_[curIdx_]->start(target_);
|
||||
cur->step(remainingDt);
|
||||
remainingDt = 0;
|
||||
curIdx_++;
|
||||
if (curIdx_ < acts_.size()) {
|
||||
acts_[curIdx_]->start(target_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -143,6 +154,20 @@ void Spawn::stop() {
|
|||
ActInterval::stop();
|
||||
}
|
||||
|
||||
void Spawn::step(f32 dt) {
|
||||
elap_ += dt;
|
||||
|
||||
for (auto* a : acts_) {
|
||||
if (auto* interval = dynamic_cast<ActInterval*>(a)) {
|
||||
if (!interval->done()) {
|
||||
interval->step(dt);
|
||||
}
|
||||
} else {
|
||||
a->step(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::update(f32 t) {
|
||||
for (auto* a : acts_) {
|
||||
if (auto* interval = dynamic_cast<ActInterval*>(a)) {
|
||||
|
|
@ -211,6 +236,27 @@ void Repeat::stop() {
|
|||
ActInterval::stop();
|
||||
}
|
||||
|
||||
void Repeat::step(f32 dt) {
|
||||
if (!inner_) {
|
||||
elap_ = dur_;
|
||||
return;
|
||||
}
|
||||
|
||||
elap_ += dt;
|
||||
|
||||
if (auto* interval = dynamic_cast<ActInterval*>(inner_)) {
|
||||
interval->step(dt);
|
||||
|
||||
if (interval->done()) {
|
||||
cnt_++;
|
||||
if (!done()) {
|
||||
inner_->stop();
|
||||
inner_->start(target_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Repeat::update(f32 t) {
|
||||
if (!inner_) return;
|
||||
|
||||
|
|
@ -250,18 +296,31 @@ void RepeatForever::start(Node* t) {
|
|||
void RepeatForever::step(f32 dt) {
|
||||
if (!inner_) return;
|
||||
|
||||
elap_ += dt;
|
||||
|
||||
if (dur_ > 0) {
|
||||
while (elap_ >= dur_) {
|
||||
elap_ -= dur_;
|
||||
inner_->stop();
|
||||
inner_->start(target_);
|
||||
}
|
||||
f32 remainingDt = dt;
|
||||
int maxIterations = 100;
|
||||
int iterations = 0;
|
||||
|
||||
if (auto* interval = dynamic_cast<ActInterval*>(inner_)) {
|
||||
f32 t = elap_ / dur_;
|
||||
interval->update(interval->easeTime(t));
|
||||
while (remainingDt > 0.0001f && iterations < maxIterations) {
|
||||
iterations++;
|
||||
if (auto* interval = dynamic_cast<ActInterval*>(inner_)) {
|
||||
f32 neededDt = interval->dur() - interval->elap();
|
||||
if (neededDt < 0.0001f) {
|
||||
neededDt = interval->dur();
|
||||
}
|
||||
if (remainingDt >= neededDt) {
|
||||
interval->step(neededDt);
|
||||
remainingDt -= neededDt;
|
||||
inner_->stop();
|
||||
inner_->start(target_);
|
||||
} else {
|
||||
interval->step(remainingDt);
|
||||
remainingDt = 0;
|
||||
}
|
||||
} else {
|
||||
inner_->step(remainingDt);
|
||||
remainingDt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,7 @@ Mat3 Node::local() const {
|
|||
Mat3 m(1.0f);
|
||||
|
||||
m = glm::translate(m, pos.toGlm());
|
||||
|
||||
m = glm::translate(m, glm::vec2(anchor.x * scale.x, anchor.y * scale.y));
|
||||
m = glm::rotate(m, rot);
|
||||
m = glm::translate(m, glm::vec2(-anchor.x * scale.x, -anchor.y * scale.y));
|
||||
|
||||
m = glm::rotate(m, rot * DEG_TO_RAD);
|
||||
m = glm::scale(m, scale.toGlm());
|
||||
|
||||
return m;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ void SceneGraph::traverseRecursive(Node* node, const std::function<void(Node*)>&
|
|||
void SceneGraph::update(f32 dt) {
|
||||
traverse([dt](Node* node) {
|
||||
node->onUpdate(dt);
|
||||
node->updateActs(dt);
|
||||
node->updateComps(dt);
|
||||
node->lateUpdateComps(dt);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -378,13 +378,13 @@ TEST(Seq, Sequence) {
|
|||
|
||||
seq->start(node.get());
|
||||
|
||||
seq->update(0.0f);
|
||||
seq->step(0.0f);
|
||||
TEST_ASSERT_TRUE(vec2Equal(node->pos, Vec2(0, 0)));
|
||||
|
||||
seq->update(0.5f);
|
||||
seq->step(0.5f);
|
||||
TEST_ASSERT_TRUE(vec2Equal(node->pos, Vec2(100, 0)));
|
||||
|
||||
seq->update(0.5f);
|
||||
seq->step(0.5f);
|
||||
TEST_ASSERT_TRUE(vec2Equal(node->pos, Vec2(100, 100)));
|
||||
|
||||
TEST_ASSERT_TRUE(seq->done());
|
||||
|
|
@ -402,7 +402,7 @@ TEST(Seq, SingleAction) {
|
|||
|
||||
seq->start(node.get());
|
||||
|
||||
seq->update(0.5f);
|
||||
seq->step(0.5f);
|
||||
TEST_ASSERT_TRUE(vec2Equal(node->pos, Vec2(100, 0)));
|
||||
|
||||
TEST_ASSERT_TRUE(seq->done());
|
||||
|
|
@ -426,11 +426,11 @@ TEST(Spawn, Parallel) {
|
|||
|
||||
spawn->start(node.get());
|
||||
|
||||
spawn->update(0.5f);
|
||||
spawn->step(0.5f);
|
||||
TEST_ASSERT_TRUE(vec2Equal(node->pos, Vec2(50, 50)));
|
||||
TEST_ASSERT_TRUE(std::abs(node->rot - 45.0f) < EPSILON);
|
||||
|
||||
spawn->update(0.5f);
|
||||
spawn->step(0.5f);
|
||||
TEST_ASSERT_TRUE(vec2Equal(node->pos, Vec2(100, 100)));
|
||||
TEST_ASSERT_TRUE(std::abs(node->rot - 90.0f) < EPSILON);
|
||||
|
||||
|
|
@ -452,7 +452,7 @@ TEST(Repeat, RepeatTimes) {
|
|||
repeat->start(node.get());
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
repeat->update(0.5f);
|
||||
repeat->step(0.5f);
|
||||
}
|
||||
|
||||
TEST_ASSERT_TRUE(vec2Equal(node->pos, Vec2(300, 0)));
|
||||
|
|
@ -474,7 +474,7 @@ TEST(RepeatForever, NeverDone) {
|
|||
repeat->start(node.get());
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
repeat->update(1.0f);
|
||||
repeat->step(1.0f);
|
||||
TEST_ASSERT_FALSE(repeat->done());
|
||||
}
|
||||
|
||||
|
|
@ -617,6 +617,6 @@ TEST(ActInterval, CustomEasing) {
|
|||
act.ease([](f32 t) { return t * t * t; });
|
||||
act.start(node.get());
|
||||
|
||||
act.update(0.5f);
|
||||
act.step(0.5f);
|
||||
TEST_ASSERT_TRUE(std::abs(node->pos.x - 12.5f) < EPSILON);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,13 +267,22 @@ TEST(Director, MultipleSceneSwitches) {
|
|||
scene1->setName("Scene1");
|
||||
director.run(scene1);
|
||||
|
||||
std::vector<Ref<TestScene>> scenes;
|
||||
scenes.push_back(scene1);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto newScene = ptr::make<TestScene>();
|
||||
newScene->setName("Scene" + std::to_string(i + 2));
|
||||
director.replace(newScene);
|
||||
scenes.push_back(newScene);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQ(5, scene1->exitCount);
|
||||
TEST_ASSERT_EQ(1, scenes[0]->exitCount);
|
||||
TEST_ASSERT_EQ(1, scenes[1]->exitCount);
|
||||
TEST_ASSERT_EQ(1, scenes[2]->exitCount);
|
||||
TEST_ASSERT_EQ(1, scenes[3]->exitCount);
|
||||
TEST_ASSERT_EQ(1, scenes[4]->exitCount);
|
||||
TEST_ASSERT_EQ(0, scenes[5]->exitCount);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -294,6 +294,10 @@ public:
|
|||
|
||||
int value;
|
||||
|
||||
void onInit() override {
|
||||
anchor = defaultAnchor();
|
||||
}
|
||||
|
||||
protected:
|
||||
Vec2 defaultAnchor() const override { return Vec2(0.0f, 0.0f); }
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue