C++ 状态:事件序列不是纯面向对象的
C++ States: Sequence of Events is not very object orientated
我正在努力使我的代码更加面向对象。
我有一个小程序希望完成 2 个非常简单的状态:输入状态和结果状态。
输入状态似乎很容易解决,因为虽然它是图形化的,但它是 "self-updating." 用户在屏幕上放置和移除精灵以产生输入。
结果状态让我很烦,因为我为它生成了一些非常丑陋的代码,根本不是面向对象的。
此状态需要按顺序做事,我正在努力寻找如何使用对象完成此操作的示例。它基本上是一些具有相同对象的动画:这里是一些伪代码。
Static int objectx = 120, object y = 120;
Static int state=0
switch(state)
{
Case 0:
//....move object right
//....once object is far enough right
state = 1;
Case 1:
//....move object down
//....once object is far enough down
state = 2;
...etc
所以我猜它需要转向拥有某种状态引擎,但我正在努力了解如何使用状态完成顺序事件。这些状态始终相同,因此可以硬编码,它们不会根据给定的输入而改变。
如有任何帮助,我们将不胜感激。
更新
也许我们可以把这第二个状态想象成一个二维游戏的过场动画。我们想要一个角色走到屏幕上,说些什么然后走开。
所以我目前的做法是通过 switch 语句管理这部分程序状态。每次我们在程序的 "result" 部分时都会调用此函数,并且我们正在使用 switch 语句来更新精灵的位置。一旦我们到达第一组动作的末尾,我们就会移动到下一个 switch 语句并继续这样做直到它完成。它 有效 但我希望使用“游戏状态” Class,它可以拥有图形和声音的所有权,并适当地移动东西。
注意:由于我没有任何上下文,所以在这里做一些假设。
听起来每个精灵都应该有自己的循环,而不是让整个游戏逻辑围绕精灵移动。
将其改编为面向对象的设计,您可以将每个精灵包装在一些
class:
class NPC : Sprite {
private:
Position CurrentPosition;
int CurrentState;
public:
virtual void Think() = 0;
virtual void Render() = 0;
};
然后你可以从这个class继承特定的精灵:
class GobbledyGook : NPC {
private:
const int FinalState = 10;
public:
bool Completed = false;
void Think() override {
if(Completed)
return;
switch(CurrentState) {
// ... repeating logic here ...
}
CurrentState++;
if(CurrentState == FinalState)
Completed = true;
}
void Render() override {
// ... draw the sprite ...
}
}
然后您可以从主游戏逻辑更新每个精灵:
// Spawn a GobbledyGook into existence.
my_npcs.insert(new GobbledyGook());
// In frame logic.
bool finished = true;
for( NPC* n : my_npcs )
{
n->Think();
if(!n->Completed)
finished = false;
}
if(finished) {
// Result state.
}
// In render logic.
for( NPC* n : my_npcs )
{
n->Render();
}
你自然也可以对整个场景采用这种逻辑:
class Intro : Cutscene {
private:
vector<NPC*> SceneSprites;
public:
void Think() override {
switch(CurrentState) {
...
}
for( NPC* n : SceneSprites ) {
n->Think();
}
}
...
};
至于是否应该删除或更改状态的使用,您打算从中获得什么?
如果不了解当前方法的所有缺陷,就很难推荐不同的方法。
我正在努力使我的代码更加面向对象。
我有一个小程序希望完成 2 个非常简单的状态:输入状态和结果状态。
输入状态似乎很容易解决,因为虽然它是图形化的,但它是 "self-updating." 用户在屏幕上放置和移除精灵以产生输入。
结果状态让我很烦,因为我为它生成了一些非常丑陋的代码,根本不是面向对象的。
此状态需要按顺序做事,我正在努力寻找如何使用对象完成此操作的示例。它基本上是一些具有相同对象的动画:这里是一些伪代码。
Static int objectx = 120, object y = 120;
Static int state=0
switch(state)
{
Case 0:
//....move object right
//....once object is far enough right
state = 1;
Case 1:
//....move object down
//....once object is far enough down
state = 2;
...etc
所以我猜它需要转向拥有某种状态引擎,但我正在努力了解如何使用状态完成顺序事件。这些状态始终相同,因此可以硬编码,它们不会根据给定的输入而改变。
如有任何帮助,我们将不胜感激。
更新
也许我们可以把这第二个状态想象成一个二维游戏的过场动画。我们想要一个角色走到屏幕上,说些什么然后走开。
所以我目前的做法是通过 switch 语句管理这部分程序状态。每次我们在程序的 "result" 部分时都会调用此函数,并且我们正在使用 switch 语句来更新精灵的位置。一旦我们到达第一组动作的末尾,我们就会移动到下一个 switch 语句并继续这样做直到它完成。它 有效 但我希望使用“游戏状态” Class,它可以拥有图形和声音的所有权,并适当地移动东西。
注意:由于我没有任何上下文,所以在这里做一些假设。
听起来每个精灵都应该有自己的循环,而不是让整个游戏逻辑围绕精灵移动。 将其改编为面向对象的设计,您可以将每个精灵包装在一些 class:
class NPC : Sprite {
private:
Position CurrentPosition;
int CurrentState;
public:
virtual void Think() = 0;
virtual void Render() = 0;
};
然后你可以从这个class继承特定的精灵:
class GobbledyGook : NPC {
private:
const int FinalState = 10;
public:
bool Completed = false;
void Think() override {
if(Completed)
return;
switch(CurrentState) {
// ... repeating logic here ...
}
CurrentState++;
if(CurrentState == FinalState)
Completed = true;
}
void Render() override {
// ... draw the sprite ...
}
}
然后您可以从主游戏逻辑更新每个精灵:
// Spawn a GobbledyGook into existence.
my_npcs.insert(new GobbledyGook());
// In frame logic.
bool finished = true;
for( NPC* n : my_npcs )
{
n->Think();
if(!n->Completed)
finished = false;
}
if(finished) {
// Result state.
}
// In render logic.
for( NPC* n : my_npcs )
{
n->Render();
}
你自然也可以对整个场景采用这种逻辑:
class Intro : Cutscene {
private:
vector<NPC*> SceneSprites;
public:
void Think() override {
switch(CurrentState) {
...
}
for( NPC* n : SceneSprites ) {
n->Think();
}
}
...
};
至于是否应该删除或更改状态的使用,您打算从中获得什么?
如果不了解当前方法的所有缺陷,就很难推荐不同的方法。