I know this has been asked before but I would like some things cleared up.
I understand that game logic and rendering should be separated but my problem is more or less how? For instance, should the renderer get ALL info from the sprite/object and use that to draw? Also should the renderer be a seperate class or member function. If it's a separate class should it be able to get the necessary info via public functions or should it be a friend of the class to draw it?
Also some clarification as to what the main object should contain, e.g, is it okay for the main class to have other sprites, shapes, fonts, and effect data? Or, should the renderer somehow contain or produce that data?
I'm asking this because I'm making a menu list class in SFML. And, although it technically works, I'm confused because it's implemented in a way that is considered by many to be bad. Thus, I would like to know as to how to implement it and fix it correctly because I have currently blended both the logic and rendering together.
class MenuList {
private:
bool m_visibility{ true };
std::vector<std::pair<MenuItem, sf::Text>> m_items;
sf::RenderWindow& m_window;
SEL::EventManager& m_manager;
sf::Font m_font;
sf::RectangleShape m_highlighter;
sf::Color m_highlightColor;
sf::RectangleShape m_box;
size_t m_size{ 0 };
size_t m_rowSpacing;
static const uint16_t indent;
public:
MenuList(sf::RenderWindow& window, SEL::EventManager& manager);
~MenuList();
// get a certain option, no range checking
MenuItem& operator[](size_t index);
// get a certain option, with range checking
// will report an error to the console if range is out of bounds
MenuItem& getOption(size_t index);
// update the menu
void Update();
// set the visibility of the menu
void setVisibility(bool value);
// get the visibility of the menu
bool getVisibility() const;
// add another option
void addOption(const MenuItem& item);
// add multiple options via a list { }
void addOption(std::initializer_list<MenuItem> items);
// remove an options index
void removeOption(size_t index);
// remove an option by name
void removeOption(const sf::String& name);
// resize the amount of submenus
void resize(size_t size);
// get the local position of the menubox
sf::FloatRect getLocalBounds();
// set the amount of spacing between each menu in pixels
void setRowSpacing(size_t rowSpacing);
// get the amount of spacing is in between each menu in pixels
size_t getRowSpacing() const;
//void addSeperator(size_t index, sf::PrimitiveType Type = sf::PrimitiveType::LinesStrip);
// get the amount of sub menus
size_t getMenuCount() const noexcept;
// get the position of the menu, the top left
const sf::Vector2f& getPosition() const noexcept;
// move the menu to a completely new position, overides the previous position
void setPosition(float x, float y);
// move the menu to a completely new position, overides the previous position
void setPosition(const sf::Vector2f& pos);
void setOutlineThickness(size_t thickness);
size_t getOutlineThickness() const;
// reset the menu such as the size, menus, and box
void reset();
};
MenuList
is not a typical game objects. The advice we might give for making a character or whatever is almost completely irrelevant for UI widgets. You can still separate logic from presentation and from rendering (e.g., separate the controller from the layout and from theme rendering) but the approach there is usually not the same as for game objects. In this day and age, I'd probably recommend you to model your UI code more after the Web (DOM, CSS, box model, etc.) than a game engine (in fact, just use the Web and embed CEF or something for your menu UI). \$\endgroup\$