我一直在处理我正在处理的程序的基本结构问题。我是一个非常缺乏经验的程序员,试图教自己使用多个状态的程序的基础知识。
现在,我有一个非常简单的游戏程序,带有一个游戏循环,可以将事件,逻辑和渲染重定向到我的StateManager类,它将状态推送到弹出状态。然后,StateManager类将事件,逻辑和呈现重定向到向量的back()上的任何状态。这个想法是为程序的每个阶段提供各种不同的状态(在这种情况下是一个带有启动画面,菜单,游戏,死亡屏幕等的简单游戏)......
然而,我是一个非常新手的编码器(尽力学习),而且我从第一个州级课程开始遇到一个基本的问题...
我创建的第一个类是SplashScreenState。并且基本概念是具有基本上仅显示一系列“闪屏图像”的状态(例如,为了示例),并且每次用户按下键时,它切换到下一图像,并且最后(当它没有飞溅屏幕图像循环时)切换到下一个状态(menustate)。
我的问题是我很难弄清楚如何构建它。最初,我错误地将每个不同的启动画面图像视为SplashScreenState的一个实例。但是,我认为这样做是不正确的,因为所有3个启动画面在技术上都属于同一个“状态”。
现在我有两个主要问题:
第一个问题是我不确定如何/在哪里存储所有的闪屏图像。如果我想在程序启动时在3个不同的屏幕图像之间循环,我应该让它们成为SplashScreenState类的所有成员吗?或者只是为'currentImage'设置一个类成员更聪明,每次用户点击一个键时它运行一个load()函数来将下一个图像加载到currentImage指针中?制作图像的数组或矢量并循环通过它们会更好吗?我只是不确定......
我的第二个问题是SplashScreenState的eventhandling()..我知道我希望屏幕上的图像改变像; * image1 - >图像2 - >图像3 - > changeState(menuState)..因此,每次用户点击键盘上的键时,它都会切换到下一个闪屏,直到最后一个闪屏,然后它会将状态更改为主菜单。我不确定这样做的最佳方式是:我应该为每个启动画面创建一个枚举并通过它们递增(直到它改变状态的最终屏幕)?我还认为,如果我将所有不同的屏幕存储在一个数组中,那么我可以很容易地通过它们增加,但那样会不会优化,因为所有屏幕都必须始终存储在内存中?
无论如何,我知道这个问题可能是非常基本和无趣的,但不幸的是,这就是我现在所处的位置!我没有接受任何正规的编程教育,而且我一直在教自己,所以我非常感谢本网站提供的所有帮助和专业知识! ^^
谢谢!
答案 0 :(得分:1)
您似乎在面向对象与处理状态转换的过程范例之间徘徊。另一个答案表明switch语句处理枚举状态更改是一个很好的程序方法。缺点是你可能最终得到一个单片游戏类,它包含所有代码和所有多余的特定于状态的数据,用于处理所有可能状态的事件/逻辑/渲染。处理这种情况的面向对象的方法更加清晰,并将它们封装到它们自己的独立状态对象中,在这些对象中可以通过共享接口以多态方式使用它们。然后,您的游戏类不需要保存处理游戏类中所有状态的所有细节,而只需要存储状态指针,而不必担心具体状态对象的实现细节。这将处理状态转换的责任移出游戏类并进入它所属的州级。您应该从设计模式书中了解状态/策略模式。处理状态的变化应该是状态对象本身的责任。这是一些阅读:
http://www.codeproject.com/Articles/14325/Understanding-State-Pattern-in-C
http://sourcemaking.com/design_patterns/state
http://sourcemaking.com/design_patterns/state/cpp/1
http://codewrangler.home.comcast.net/~codewrangler/tech_info/patterns_code.html#State
http://en.wikipedia.org/wiki/State_pattern
http://www.codeproject.com/Articles/38962/State-Design-Pattern
引用设计模式和面向模式的软件架构书籍: 基于模式的方法使用代码而不是数据结构来指定状态转换,但是很好地适应了状态转换操作。状态模式未指定必须定义状态转换的位置。它可以在上下文对象中完成,也可以在每个单独的派生状态类中完成。让状态子类指定其后继状态以及何时进行转换通常更灵活和适当。
您可以选择提前创建状态对象并且永远不会破坏它们,这可能在状态变化快速发生时很好,并且您希望避免破坏可能需要的状态。另一方面,它可能不方便,因为上下文必须保持对可能输入的所有状态的引用。
当在运行时不知道将要输入的状态且上下文不经常更改状态时,最好根据需要创建状态对象并在此后销毁它们。在确定使用哪个时,您需要考虑成本和转换频率。
答案 1 :(得分:1)
首先要解释你的问题。
管理启动画面的游戏部分可以通过两种方式运行。你已经检查了这个问题,它真的很简单:
接收输入;设置下一个州。
所以,例子:
STATE_SPLASH1
STATE_SPLASH2
STATE_SPLASH3
STATE_TITLE
STATE_GAME_INIT
STATE_GAME
STATE_EXIT
伪代码:
state = STATE_SPLASH1
while (state != STATE_EXIT)
... receive input ...
... process events to responders ...
... update ...
... yadda yadda ...
switch (state) {
case STATE_SPLASH1:
show_splash1()
case STATE_SPLASH2:
show_splash2()
case ..:
case STATE_TITLE:
show_title()
case STATE_GAME_INIT:
show_loading()
setup_level()
setup_characters()
case STATE_GAME:
game_update()
case STATE_EXIT:
cleanup_and_quit()
另一种方法是管理启动“游戏状态”,然后将启动状态作为内部状态。当splash没有更多的逻辑运行时,将游戏状态设置为下一个。在我学习的过程中,我发现DOOM源是一个宝贵的资源和人,只不过是数百台状态机。 :)