首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >通用2D仿真发动机

通用2D仿真发动机
EN

Code Review用户
提问于 2015-01-22 05:33:32
回答 2查看 149关注 0票数 2

我正在使用SFML来管理我的窗口,我正在编写这个引擎来可视化一些PSO的工作。我试图使它具有足够的通用性,以便我可以将其扩展到以后的其他模拟中,并尽可能地将其保持在最低限度。(我将把这个设计模式复制到一个免费初始化的openGL 3D引擎w/CUDA中,因此这里将进行性能分析。)

这将是一个伟大的帮助,在它之前提供一些技术和设计技巧,在我继续和变得太深,使它容易返工。我想这方面的相关知识主要是gameloop设计和类结构,但这基本上是框架代码。请学究,但不要刻薄!

我将在任何地方实现异常捕获,我想确保我正在尽可能多地划分,但不要太多!也许有一些方法可以以不同的方式存储我的变量或实现处理程序。基本上,让我知道一般的良好编码实践,您认为我可能已经结束或不足。

main.cpp

代码语言:javascript
运行
复制
#include "App.h"

int main()
{
    class GE gol;
    gol.run();

    return 0;
}

App.h

代码语言:javascript
运行
复制
#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:
};

App.cpp

代码语言:javascript
运行
复制
#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;
}
EN

回答 2

Code Review用户

回答已采纳

发布于 2015-01-22 17:19:24

正如@David在他的回答中很好地指出的那样,如果您的目的是在此基础上构建更多的类,那么您将希望将责任划分为不同的类。在设计时要记住的一个好事情是单一责任原则。设计每个类只做一件事,但这一件事做得很好。

代码审查:

  • 我没有在您的头文件中看到一个包括护卫。如果你没有一个,你肯定要加上它。
  • App是从它继承的,所以它应该有一个virtual析构函数。如果您的目标是C++11,您可以声明一个默认的虚拟析构函数,因为您目前没有执行任何手动清理: virtual ()= default;
  • _Uint32t,这种类型是从哪里来的?这是不标准的,_前缀告诉我,它可能是一个库或编译器的内部细节。使用中的标准大小类型。
  • 当您直接在类主体中声明和定义类方法时,inline是隐式的。应该删除它以避免冗余。
  • 使用booleans而不是返回代码。您的方法在成功时返回0,这很容易出错。一个bool和一个true关于成功和false在失败是清楚得多。
  • 我没有明白_s后缀在布尔quit_svs_s上的意义。而且,vs_s也不可能猜出它的含义。请给它取个更好的名字。(好的,在环顾四周之后,您发现它代表V,所以只需将其命名为:vsyncEnabled或类似的)。
  • 显式地从char *构造字符串,如这里::App(sf::VideoMode::getDesktopMode(),std::string (“生命游戏”),sf::Style::None),因为std::string隐式地从char数组构造字符串。这样做可能会更糟,因为它可能会创建一个额外的字符串副本,该字符串将在下一行中丢弃。一些编译器不会优化这个微小的错误。这些小事情很好地提醒我们,我们应该停止帮助编译器 ;)
票数 2
EN

Code Review用户

发布于 2015-01-22 07:27:07

我首先担心的是,App类(或子类)将负责事件处理、渲染、资源、物理等的所有逻辑,这对于一个类来说是一个很大的责任。为此有几个类将更易于维护,例如:

  • App负责实例化和耦合所有其他类,也许还负责基本的gameloop。
  • ResourceManager负责获取和释放资源
  • EventHandlerControler负责事件或用户输入。
  • PhysicsEngine将处理物理问题

这样,每个类都有它自己的责任,但是相互之间的交互会稍微困难一些。

我注意到的另一件事是:

代码语言:javascript
运行
复制
class GE gol;

在这种情况下,不需要class关键字。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/78284

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档