Witam!
Mam pytanie dotyczące dostępu do okna w SFML, chciałbym uniknąć używania zmiennych globalnych i przekazywanie zmiennej okna przez argumenty funkcji. Czy pytanie jest jakiś dobry sprawdzony sposób na zapewnienie dostępu do tej zmiennej? I paru innych rzeczy które mi ułatwią znacznie programowanie w SFML.
Czytałem coś o singletonie, ale myślę że to jest przerost formy nad treścią w przypadku prostego Tower Defense.
Cześć. Sam jestem właśnie w procesie tworzenia tej samej gry co Ty w SFML.
Ja mam w swoim kodzie kilka klas przyjmujących argument sf::RenderWindow & w metodzie draw(sf::RenderWindow &window).
Rzecz w tym, że jeżeli chcesz narysować jakiś obiekt możesz dziedziczyć w klasie tego obiektu po sf::Drawable i implementować co ma być rysowane w w tym obiekcie dzięki czemu nie musisz przekazywać do tej klasy sf::RenderWindow & tylko możesz z poziomu wyżej rysować np.
class tower :public sf::Drawable
{
sf::Sprite sprite;
sf::RectangleShape shape;
bullet bulletor; //klasa bullet dziedziczy po sf::Drawable i też ma zaimplementowane co ma być rysowane w niej.
public:
void draw(sf::RenderTarget & target, sf::RenderStates states) const; //nadpisywana metoda wirtualna
{
target.draw(sprite);
target.draw(shape);
target.draw(bulletor);
};
W tym momencie możesz wykonywać metodę window.draw(ObiektKlasyTower).
Właśnie chciałem tego uniknąć, korzystam z tej metody i mi to nie odpowiada.
Przekazywanie obiektu okna do wszystkiego przez referencje jest dość irytujące.
Nie wiem czy to eleganckie rozwiązanie, ale jak masz na przykład klasę od GUI, to możesz jej przekazać referencję do okna a potem pisać tylko gui.draw()
Właśnie nie wiem też czy jest to eleganckie i dlatego poszukuję lepszego jeżeli takie jest.
Popatrz w ur::{...player, ...flower}
, nie masz tam żadnego przekazywania okna - jawnie, ofc. Wystarczy to odpowiednio ukryć.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct events {};
struct image {};
struct render_target {
void draw(image const &image, int x, int y) {}
};
struct drawable {
virtual void draw(render_target &target) const = 0;
virtual ~drawable() = default;
};
struct updatable {
virtual void update(int delta_time) = 0;
virtual ~updatable() = default;
};
struct events_consumer {
virtual void consume(events const &events) = 0;
virtual ~events_consumer() = default;
};
namespace scaffolding {
struct entity: drawable, updatable, events_consumer {
int x, y;
image img;
entity(image img, int x, int y): img(img), x(x), y(y){}
virtual void draw(render_target &target) const override {
target.draw(img, x, y);
}
virtual void consume(events const &evts) override {}
virtual void update(int dt) override {}
};
using entities = std::vector<entity>;
struct game_skeleton: drawable, updatable, events_consumer {
entities entities_container;
bool is_running() const {
return false; //normalny u'd like it to be this.is_running variable
}
virtual void update(int dt) override {
for(auto &&e: get_entities()) {
e.update(dt);
}
}
virtual void draw(render_target &target) const override {
for(auto &&e: get_entities()) {
e.draw(target);
}
}
virtual void consume(events const &evts) {
for(auto &&e: get_entities()) {
e.consume(evts);
}
}
entities &get_entities() { return entities_container; }
entities const &get_entities() const { return entities_container; }
void register_entity(entity &&e, std::string const &id) {}
entity &get_entity(std::string const &id) {}
entity const &get_entity(std::string const &id) const {}
void unregister_entity(std::string const &id) {}
};
struct game_runner {
game_skeleton &game;
render_target ⌖
int fetch_dt() {
return {};
}
events fetch_events() {
return {};
}
void run() {
while(game.is_running()) {
stream_events();
stream_time();
}
}
void stream_events() {
game.consume(fetch_events());
}
void stream_time() {
game.update(fetch_dt());
game.draw(target);
}
};
}
namespace ur {
image load_img(std::string const &) { return {}; }
struct flower_entity: scaffolding::entity {
flower_entity(int x, int y): entity(load_img("flower.png"), x, y) {}
};
struct fancy_player_entity: scaffolding::entity {
fancy_player_entity(int x, int y): entity(load_img("sausage.png"), x, y) {}
virtual void update(int dt) override {
//apply some kind of physics mb?
}
virtual void consume(events const &) override {
//mb handle the keyboard or smtg
}
};
struct game: scaffolding::game_skeleton {
game() {
register_entity(flower_entity(5, 5), "flower-1");
register_entity(fancy_player_entity(10, 10), "player");
register_entity(flower_entity(5, 6), "flower-2");
}
};
}
int main() {
auto target = render_target {};
auto game = ur::game {};
scaffolding::game_runner {game, target}.run();
return 0;
}
Czegoś takiego właśnie szukałem! Dziękuje.