I asked for feedback on my Dice
class and I was suggested that I should separate logic from view. I decided to completely refactor my project and I'd like to share a small piece of it (the Dice
class and connection between logic and view) and ask for feedback again.
So lets start with logic::Dice
namespace logic {
class Dice {
std::default_random_engine rng;
int m_currentNumber;
public:
Dice() {
rng.seed(static_cast<int>(std::chrono::system_clock::now().time_since_epoch().count()));
}
~Dice() = default;
void rollNewNumber();
int getCurrentNumber() const;
};
}
void logic::Dice::rollNewNumber() {
std::uniform_int_distribution<int> dist(1, 6);
m_currentNumber = dist(rng);
}
int logic::Dice::getCurrentNumber() const {
return m_currentNumber;
}
Now view::Dice
namespace view {
class Dice {
sf::Texture m_texture;
sf::RectangleShape m_shape;
sf::SoundBuffer m_buffer;
sf::Sound m_sound;
public:
Dice();
~Dice() = default;
sf::RectangleShape& get();
void changeTexture(int);
void playSound();
};
}
view::Dice::Dice() {
m_shape.setSize(sf::Vector2f(DICE_WIDTH, DICE_HEIGHT));
if (!m_texture.loadFromFile(DICE_TEXTURE)) std::cout << "Can't load texture.\n";
m_shape.setTexture(&m_texture);
m_shape.setTextureRect(sf::IntRect(0, 0, 55, 55));
if (!m_buffer.loadFromFile(DICE_SOUND)) std::cout << "Can't load sound.\n";
m_sound.setBuffer(m_buffer);
}
sf::RectangleShape& view::Dice::get() {
return m_shape;
}
void view::Dice::changeTexture(int newNumber) {
switch (newNumber) {
case 1: {
m_shape.setTextureRect(sf::IntRect(0, 0, 55, 55));
break;
}
case 2: {
m_shape.setTextureRect(sf::IntRect(55, 0, 55, 55));
break;
}
case 3: {
m_shape.setTextureRect(sf::IntRect(110, 0, 55, 55));
break;
}
case 4: {
m_shape.setTextureRect(sf::IntRect(165, 0, 55, 55));
break;
}
case 5: {
m_shape.setTextureRect(sf::IntRect(220, 0, 55, 55));
break;
}
case 6: {
m_shape.setTextureRect(sf::IntRect(275, 0, 55, 55));
break;
}
}
}
void view::Dice::playSound() {
m_sound.play();
}
Now to connect logic with presentation, I got 2 classes. view::GameState
which derives from view::State
that looks like that
namespace view {
class State {
public:
virtual void initialise() = 0;
virtual void handleUserInput() = 0;
virtual void update(sf::Time dt) = 0;
virtual void draw() = 0;
};
}
And most important in this case part of my view::GameState
class GameState : public State {
logic::Game m_game;
view::Dice m_diceOne, m_diceTwo;
};
And inside my view::GameState::handleUserInput()
I check when "Roll the dice" button is clicked
if (this->m_data->inputManager.isSpriteClicked(this->m_rollButton, evnt, this->m_data->window)) {
rollTheDice();
}
Which finnaly gets to connection between logic and presentation
void view::GameState::rollTheDice() {
m_game.rollTheDice();
m_diceOne.playSound();
m_diceOne.changeTexture(m_game.getDiceOne().getCurrentNumber());
m_diceTwo.changeTexture(m_game.getDiceTwo().getCurrentNumber());
}
That leads to logic::Game
class which is kind of game engine, that does all the logic and has all the logic objects like Dice
, Player
, GameBoard
namespace logic {
class Game {
logic::Dice m_diceOne, m_diceTwo;
int m_throwsInCurrentTurn = 0;
int m_doublesInCurrentTurn = 0;
int m_totalRollResult = 0;
public:
void rollTheDice();
logic::Dice& getDiceOne();
logic::Dice& getDiceTwo();
};
}
void logic::Game::rollTheDice() {
m_throwsInCurrentTurn++;
m_diceOne.rollNewNumber();
m_diceTwo.rollNewNumber();
int diceOneResult = m_diceOne.getCurrentNumber();
int diceTwoResult = m_diceTwo.getCurrentNumber();
m_totalRollResult += diceOneResult + diceTwoResult;
if (diceOneResult == diceTwoResult) m_doublesInCurrentTurn++;
}
logic::Dice& logic::Game::getDiceOne() {
return m_diceOne;
}
logic::Dice & logic::Game::getDiceTwo() {
return m_diceTwo;
}
I would appriciate your feedback and suggestions how to improve my code.