我正在使用SFML来管理我的窗口,我正在编写这个引擎来可视化一些PSO的工作。我试图使它具有足够的通用性,以便我可以将其扩展到以后的其他模拟中,并尽可能地将其保持在最低限度。(我将把这个设计模式复制到一个免费初始化的openGL 3D引擎w/CUDA中,因此这里将进行性能分析。)
这将是一个伟大的帮助,在它之前提供一些技术和设计技巧,在我继续和变得太深,使它容易返工。我想这方面的相关知识主要是gameloop设计和类结构,但这基本上是框架代码。请学究,但不要刻薄!
我将在任何地方实现异常捕获,我想确保我正在尽可能多地划分,但不要太多!也许有一些方法可以以不同的方式存储我的变量或实现处理程序。基本上,让我知道一般的良好编码实践,您认为我可能已经结束或不足。
#include "App.h"
int main()
{
class GE gol;
gol.run();
return 0;
}
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
class App {
public:
App(sf::VideoMode mode, std::string title, _Uint32t style)
: Window(mode, title, style)
{
quit_s = false, vs_s = true;
logic_ticks_sec = 60; // make ctor to handle these, default ctor will always init like this
frame_time = sf::milliseconds(1000 / logic_ticks_sec);
max_frameskip = 5;
Window.setVerticalSyncEnabled(vs_s);
}
~App()
{
}
int run();
protected:
sf::RenderWindow Window;
sf::Event Event;
//State Variables
//Timing
sf::Clock clock;
int logic_ticks_sec, max_frameskip;
sf::Time frame_time, elapsed;
// Resources
//Functions
//Event Handlers
inline void toggleVsync() { vs_s = !vs_s; Window.setVerticalSyncEnabled(vs_s); };
inline void quit() { quit_s = true; };
virtual void handleMouse();
//Resource Management
virtual int initResources();
virtual int cleanResources();
//Game Execution
virtual int gameLoop(); //not usually overridden, maybe not virtual and private?
virtual int eventLoop(); //handle events
virtual int renderLoop(); //virtual
private:
//State Variables
bool quit_s, vs_s;
sf::Vector2i mouse_pos;
};
class GE : public App // GOL example engine derivation, move to own files when App project is finished
{
public:
GE()
: App(sf::VideoMode::getDesktopMode(), std::string("Game of Life"), sf::Style::None)
{};
~GE()
{};
private:
};
#include "App.h"
//App
int App::run()
{
initResources();
gameLoop();
cleanResources();
Window.close();
return 0;
}
//Event Handlers
void App::handleMouse()
{
mouse_pos = sf::Mouse::getPosition(Window);
}
//Resource Management
int App::initResources()
{
return 0;
}
int App::cleanResources()
{
return 0;
}
//Main Loops
int App::gameLoop()
{
while (!quit_s)
{
clock.restart();
eventLoop();
renderLoop();
elapsed = clock.getElapsedTime();
}
return 0;
}
int App::eventLoop()
{
while (Window.pollEvent(Event))
{
switch (Event.type)
{
case sf::Event::Closed:
quit();
break;
case sf::Event::MouseMoved:
handleMouse();
break;
case sf::Event::KeyPressed:
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
quit();
} else
if (sf::Keyboard::isKeyPressed(sf::Keyboard::F5))
{
toggleVsync();
}
break;
case sf::Event::MouseButtonPressed:
if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left))
{
}
else
if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Right))
{
}
break;
default:
break;
}
}
//Physics
//AI
return 0;
}
int App::renderLoop()
{
Window.clear();
Window.display();
return 0;
}
发布于 2015-01-22 17:19:24
正如@David在他的回答中很好地指出的那样,如果您的目的是在此基础上构建更多的类,那么您将希望将责任划分为不同的类。在设计时要记住的一个好事情是单一责任原则。设计每个类只做一件事,但这一件事做得很好。
App
是从它继承的,所以它应该有一个virtual
析构函数。如果您的目标是C++11,您可以声明一个默认的虚拟析构函数,因为您目前没有执行任何手动清理: virtual ()= default;_Uint32t
,这种类型是从哪里来的?这是不标准的,_
前缀告诉我,它可能是一个库或编译器的内部细节。使用中的标准大小类型。inline
是隐式的。应该删除它以避免冗余。bool
和一个true
关于成功和false
在失败是清楚得多。_s
后缀在布尔quit_s
和vs_s
上的意义。而且,vs_s
也不可能猜出它的含义。请给它取个更好的名字。(好的,在环顾四周之后,您发现它代表V,所以只需将其命名为:vsyncEnabled
或类似的)。char *
构造字符串,如这里::App(sf::VideoMode::getDesktopMode(),std::string (“生命游戏”),sf::Style::None),因为std::string
隐式地从char数组构造字符串。这样做可能会更糟,因为它可能会创建一个额外的字符串副本,该字符串将在下一行中丢弃。一些编译器不会优化这个微小的错误。这些小事情很好地提醒我们,我们应该停止帮助编译器 ;)
发布于 2015-01-22 07:27:07
我首先担心的是,App
类(或子类)将负责事件处理、渲染、资源、物理等的所有逻辑,这对于一个类来说是一个很大的责任。为此有几个类将更易于维护,例如:
App
负责实例化和耦合所有其他类,也许还负责基本的gameloop。ResourceManager
负责获取和释放资源EventHandler
或Controler
负责事件或用户输入。PhysicsEngine
将处理物理问题这样,每个类都有它自己的责任,但是相互之间的交互会稍微困难一些。
我注意到的另一件事是:
class GE gol;
在这种情况下,不需要class
关键字。
https://codereview.stackexchange.com/questions/78284
复制相似问题