Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SFML/Graphics.hpp>
- #include <iostream>
- #include <memory>
- #include <map>
- #include <string>
- #include <vector>
- #include <array>
- #include <random>
- #include <stdexcept>
- #include <cassert>
- namespace
- {
- const std::string shaderCode = \
- "uniform vec2 LightOrigin;"\
- "uniform vec3 SourceColor;"\
- "uniform float LightAttenuation;"\
- "uniform vec2 ScreenResolution;"\
- "void main()"\
- "{"\
- " vec2 baseDistance = gl_FragCoord.xy;"\
- " baseDistance.y = ScreenResolution.y - baseDistance.y;"\
- " vec2 distance = LightOrigin - baseDistance;"\
- " float linearDistance = length(distance);"\
- " float attenuation = 1.0 / ((LightAttenuation + LightAttenuation) * linearDistance);"\
- " vec4 lightColor = vec4(SourceColor, 1.0);"\
- " vec4 color = vec4(attenuation, attenuation, attenuation, 1.0) * lightColor;"\
- " gl_FragColor = color;"\
- "}";
- const std::string Brightness = \
- "uniform sampler2D source;"\
- "const float Threshold = 0.7;"\
- "const float Factor = 4.0;"\
- "void main()"\
- "{"\
- " vec4 sourceFragment = texture2D(source, gl_TexCoord[0].xy);"\
- " float luminance = sourceFragment.r * 0.2126 + sourceFragment.g * 0.7152 + sourceFragment.b * 0.0722;"\
- " sourceFragment *= clamp(luminance - Threshold, 0.0, 1.0) * Factor;"\
- " gl_FragColor = sourceFragment;"\
- "}";
- const std::string GuassianBlur = \
- "uniform sampler2D source;"\
- "uniform vec2 offsetFactor;"\
- "void main()"\
- "{"\
- " vec2 textureCoordinates = gl_TexCoord[0].xy;"\
- " vec4 color = vec4(0.0);"\
- " color += texture2D(source, textureCoordinates - 4.0 * offsetFactor) * 0.0162162162;"\
- " color += texture2D(source, textureCoordinates - 3.0 * offsetFactor) * 0.0540540541;"\
- " color += texture2D(source, textureCoordinates - 2.0 * offsetFactor) * 0.1216216216;"\
- " color += texture2D(source, textureCoordinates - offsetFactor) * 0.1945945946;"\
- " color += texture2D(source, textureCoordinates) * 0.2270270270;"\
- " color += texture2D(source, textureCoordinates + offsetFactor) * 0.1945945946;"\
- " color += texture2D(source, textureCoordinates + 2.0 * offsetFactor) * 0.1216216216;"\
- " color += texture2D(source, textureCoordinates + 3.0 * offsetFactor) * 0.0540540541;"\
- " color += texture2D(source, textureCoordinates + 4.0 * offsetFactor) * 0.0162162162;"\
- " gl_FragColor = color;"\
- "}";
- const std::string DownSample = \
- "uniform sampler2D source;"\
- "uniform vec2 sourceSize;"\
- "void main()"\
- "{"\
- " vec2 pixelSize = vec2(1.0 / sourceSize.x, 1.0 / sourceSize.y);"\
- " vec2 textureCoordinates = gl_TexCoord[0].xy;"\
- " vec4 color = texture2D(source, textureCoordinates);"\
- " color += texture2D(source, textureCoordinates + vec2(1.0, 0.0) * pixelSize);"\
- " color += texture2D(source, textureCoordinates + vec2(-1.0, 0.0) * pixelSize);"\
- " color += texture2D(source, textureCoordinates + vec2(0.0, 1.0) * pixelSize);"\
- " color += texture2D(source, textureCoordinates + vec2(0.0, -1.0) * pixelSize);"\
- " color += texture2D(source, textureCoordinates + vec2(1.0, 1.0) * pixelSize);"\
- " color += texture2D(source, textureCoordinates + vec2(-1.0, -1.0) * pixelSize);"\
- " color += texture2D(source, textureCoordinates + vec2(1.0, -1.0) * pixelSize);"\
- " color += texture2D(source, textureCoordinates + vec2(-1.0, 1.0) * pixelSize);"\
- " gl_FragColor = color / 9.0;"\
- "}";
- const std::string Add = \
- "uniform sampler2D source;"\
- "uniform sampler2D bloom;"\
- "void main()"\
- "{"\
- " vec4 sourceFragment = texture2D(source, gl_TexCoord[0].xy);"\
- " vec4 bloomFragment = texture2D(bloom, gl_TexCoord[0].xy);"\
- " gl_FragColor = sourceFragment + bloomFragment;"\
- "}";
- const std::string Fullpass = \
- "void main()"\
- "{"\
- " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"\
- " gl_TexCoord[0] = gl_MultiTexCoord0;"\
- "}";
- }
- namespace
- {
- const sf::Vector2i WINDOW_SIZE(640, 480);
- const unsigned NUMBER_OF_PLAYERS = 2;
- const unsigned DIM = 3;
- const float SIZE = 70.f;
- const sf::Vector2f START_POINT(WINDOW_SIZE.x * 0.5f - DIM * SIZE * 0.5f, WINDOW_SIZE.y * 0.5f - DIM * SIZE * 0.5f);
- }
- enum struct Player : unsigned
- {
- None,
- User,
- Computer
- };
- enum struct Shaders : unsigned
- {
- BrightnessPass,
- DownSamplePass,
- GaussianBlurPass,
- AddPass,
- Light
- };
- enum struct Fonts : unsigned
- {
- Main,
- };
- template <typename Resource>
- void centerOrigin(Resource& resource)
- {
- sf::FloatRect bounds = resource.getLocalBounds();
- resource.setOrigin(std::floor(bounds.left + bounds.width / 2.f), std::floor(bounds.top + bounds.height / 2.f));
- }
- template <typename Resource, typename Identifier>
- class ResourceHolder
- {
- public:
- void load(Identifier id, const std::string& filename);
- template <typename Parameter>
- void load(Identifier id, const std::string& filename, const Parameter& secondParam, bool flag = true);
- Resource& get(Identifier id);
- const Resource& get(Identifier id) const;
- private:
- void insertResource(Identifier id, std::unique_ptr<Resource> resource);
- std::map<Identifier, std::unique_ptr<Resource>> mResourceMap;
- };
- template <typename Resource, typename Identifier>
- void ResourceHolder<Resource, Identifier>::load(Identifier id, const std::string& filename)
- {
- std::unique_ptr<Resource> resource(std::make_unique<Resource>());
- if (!resource->loadFromFile(filename))
- throw std::runtime_error("ResourceHolder::load - Failed to load " + filename);
- insertResource(id, std::move(resource));
- }
- template <typename Resource, typename Identifier>
- template <typename Parameter>
- void ResourceHolder<Resource, Identifier>::load(Identifier id, const std::string& filename, const Parameter& secondParam, bool flag)
- {
- std::unique_ptr<Resource> resource(std::make_unique<Resource>());
- if (flag)
- {
- if (!resource->loadFromMemory(filename, secondParam))
- throw std::runtime_error("ResourceHolder::load - Failed to load from Memory " + filename);
- }
- else
- {
- if (!resource->loadFromFile(filename, secondParam))
- throw std::runtime_error("ResourceHolder::load - Failed to load " + filename);
- }
- insertResource(id, std::move(resource));
- }
- template <typename Resource, typename Identifier>
- Resource& ResourceHolder<Resource, Identifier>::get(Identifier id)
- {
- auto found = mResourceMap.find(id);
- assert(found != mResourceMap.end());
- return *found->second;
- }
- template <typename Resource, typename Identifier>
- const Resource& ResourceHolder<Resource, Identifier>::get(Identifier id) const
- {
- auto found = mResourceMap.find(id);
- assert(found != mResourceMap.end());
- return *found->second;
- }
- template <typename Resource, typename Identifier>
- void ResourceHolder<Resource, Identifier>::insertResource(Identifier id, std::unique_ptr<Resource> resource)
- {
- auto inserted = mResourceMap.insert(std::make_pair(id, std::move(resource)));
- assert(inserted.second);
- }
- using FontHolder = ResourceHolder<sf::Font, Fonts>;
- using ShaderHolder = ResourceHolder<sf::Shader, Shaders>;
- class PostEffect : sf::NonCopyable
- {
- public:
- virtual ~PostEffect();
- virtual void apply(const sf::RenderTexture& input, sf::RenderTarget& output) = 0;
- static bool isSupported();
- protected:
- static void applyShader(const sf::Shader& shader, sf::RenderTarget& output);
- };
- PostEffect::~PostEffect()
- {
- }
- void PostEffect::applyShader(const sf::Shader& shader, sf::RenderTarget& output)
- {
- sf::Vector2f outputSize = static_cast<sf::Vector2f>(output.getSize());
- sf::VertexArray vertices(sf::TrianglesStrip, 4);
- vertices[0] = sf::Vertex(sf::Vector2f(0, 0), sf::Vector2f(0, 1));
- vertices[1] = sf::Vertex(sf::Vector2f(outputSize.x, 0), sf::Vector2f(1, 1));
- vertices[2] = sf::Vertex(sf::Vector2f(0, outputSize.y), sf::Vector2f(0, 0));
- vertices[3] = sf::Vertex(sf::Vector2f(outputSize), sf::Vector2f(1, 0));
- sf::RenderStates states;
- states.shader = &shader;
- states.blendMode = sf::BlendNone;
- output.draw(vertices, states);
- }
- bool PostEffect::isSupported()
- {
- return sf::Shader::isAvailable();
- }
- class BloomEffect final : public PostEffect
- {
- public:
- using RenderTextureArray = std::array<sf::RenderTexture, 2>;
- BloomEffect();
- void apply(const sf::RenderTexture& input, sf::RenderTarget& output) override;
- private:
- void prepareTextures(sf::Vector2u size);
- void filterBright(const sf::RenderTexture& input, sf::RenderTexture& output);
- void blurMultipass(RenderTextureArray& renderTextures);
- void blur(const sf::RenderTexture& input, sf::RenderTexture& output, sf::Vector2f offsetFactor);
- void downsample(const sf::RenderTexture& input, sf::RenderTexture& output);
- void add(const sf::RenderTexture& source, const sf::RenderTexture& bloom, sf::RenderTarget& target);
- ShaderHolder mShaders;
- sf::RenderTexture mBrightnessTexture;
- RenderTextureArray mFirstPassTextures;
- RenderTextureArray mSecondPassTextures;
- };
- BloomEffect::BloomEffect()
- : mShaders()
- , mBrightnessTexture()
- , mFirstPassTextures()
- , mSecondPassTextures()
- {
- mShaders.load(Shaders::BrightnessPass, Fullpass, Brightness);
- mShaders.load(Shaders::DownSamplePass, Fullpass, DownSample);
- mShaders.load(Shaders::GaussianBlurPass, Fullpass, GuassianBlur);
- mShaders.load(Shaders::AddPass, Fullpass, Add);
- }
- void BloomEffect::apply(const sf::RenderTexture& input, sf::RenderTarget& output)
- {
- prepareTextures(input.getSize());
- filterBright(input, mBrightnessTexture);
- downsample(mBrightnessTexture, mFirstPassTextures[0]);
- blurMultipass(mFirstPassTextures);
- downsample(mFirstPassTextures[0], mSecondPassTextures[0]);
- blurMultipass(mSecondPassTextures);
- add(mFirstPassTextures[0], mSecondPassTextures[0], mFirstPassTextures[1]);
- mFirstPassTextures[1].display();
- add(input, mFirstPassTextures[1], output);
- }
- void BloomEffect::prepareTextures(sf::Vector2u size)
- {
- if (mBrightnessTexture.getSize() != size)
- {
- mBrightnessTexture.create(size.x, size.y);
- mBrightnessTexture.setSmooth(true);
- mFirstPassTextures[0].create(size.x / 2, size.y / 2);
- mFirstPassTextures[0].setSmooth(true);
- mFirstPassTextures[1].create(size.x / 2, size.y / 2);
- mFirstPassTextures[1].setSmooth(true);
- mSecondPassTextures[0].create(size.x / 4, size.y / 4);
- mSecondPassTextures[0].setSmooth(true);
- mSecondPassTextures[1].create(size.x / 4, size.y / 4);
- mSecondPassTextures[1].setSmooth(true);
- }
- }
- void BloomEffect::filterBright(const sf::RenderTexture& input, sf::RenderTexture& output)
- {
- sf::Shader& brightness = mShaders.get(Shaders::BrightnessPass);
- brightness.setUniform("source", input.getTexture());
- applyShader(brightness, output);
- output.display();
- }
- void BloomEffect::blurMultipass(RenderTextureArray& renderTextures)
- {
- sf::Vector2u textureSize = renderTextures[0].getSize();
- for (std::size_t count = 0; count < 2; ++count)
- {
- blur(renderTextures[0], renderTextures[1], sf::Vector2f(0.f, 1.f / textureSize.y));
- blur(renderTextures[1], renderTextures[0], sf::Vector2f(1.f / textureSize.x, 0.f));
- }
- }
- void BloomEffect::blur(const sf::RenderTexture& input, sf::RenderTexture& output, sf::Vector2f offsetFactor)
- {
- sf::Shader& gaussianBlur = mShaders.get(Shaders::GaussianBlurPass);
- gaussianBlur.setUniform("source", input.getTexture());
- gaussianBlur.setUniform("offsetFactor", offsetFactor);
- applyShader(gaussianBlur, output);
- output.display();
- }
- void BloomEffect::downsample(const sf::RenderTexture& input, sf::RenderTexture& output)
- {
- sf::Shader& downSampler = mShaders.get(Shaders::DownSamplePass);
- downSampler.setUniform("source", input.getTexture());
- downSampler.setUniform("sourceSize", sf::Vector2f(input.getSize()));
- applyShader(downSampler, output);
- output.display();
- }
- void BloomEffect::add(const sf::RenderTexture& source, const sf::RenderTexture& bloom, sf::RenderTarget& output)
- {
- sf::Shader& adder = mShaders.get(Shaders::AddPass);
- adder.setUniform("source", source.getTexture());
- adder.setUniform("bloom", bloom.getTexture());
- applyShader(adder, output);
- }
- class Tile : public sf::RectangleShape, private sf::NonCopyable
- {
- public:
- Tile() = default;
- void setOwner(Player player)
- {
- mOwner = player;
- }
- Player getOwner() const
- {
- return mOwner;
- }
- void setLightColor(sf::Vector3f player)
- {
- mColor = player;
- }
- sf::Vector3f getLightColor() const
- {
- return mColor;
- }
- private:
- Player mOwner = Player::None;
- sf::Vector3f mColor = sf::Vector3f(0, 0, 0);
- };
- class World : private sf::NonCopyable
- {
- struct Move
- {
- unsigned int x = 0;
- unsigned int y = 0;
- };
- public:
- explicit World(sf::RenderTarget& outputTarget);
- bool isFull() const;
- bool isWinner(Player player) const;
- bool applyMove(Player player, sf::Uint32 row, sf::Uint32 column) const;
- bool applyAl(Player player) const;
- void draw();
- private:
- Move minimax() const;
- int minSearch(int level) const;
- int maxSearch(int level) const;
- sf::RenderTarget& mTarget;
- sf::RenderTexture mRenderTexture;
- sf::Sprite mSpriteWorld;
- ShaderHolder mShader;
- BloomEffect mBloomEffect;
- mutable unsigned mRemain;
- mutable std::array<Tile, DIM * DIM> mTiles;
- };
- World::World(sf::RenderTarget& outputTarget)
- : mTarget(outputTarget)
- , mRenderTexture()
- , mTiles()
- , mRemain(DIM * DIM)
- {
- sf::Vector2f startPosition(START_POINT);
- for (unsigned i = 0; i < DIM; ++i)
- {
- for (unsigned j = 0; j < DIM; ++j)
- {
- unsigned position = j * DIM + i;
- mTiles[position].setSize(sf::Vector2f(SIZE, SIZE));
- mTiles[position].setPosition(startPosition);
- mTiles[position].setOutlineThickness(2.f);
- mTiles[position].setFillColor(sf::Color::Black);
- mTiles[position].setOutlineColor(sf::Color::White);
- startPosition.x += SIZE;
- }
- startPosition.y += SIZE;
- startPosition.x = START_POINT.x;
- }
- mRenderTexture.create(WINDOW_SIZE.x, WINDOW_SIZE.y);
- mRenderTexture.setSmooth(true);
- mSpriteWorld.setTexture(mRenderTexture.getTexture());
- mSpriteWorld.setOrigin(mSpriteWorld.getTextureRect().width / 2.f, mSpriteWorld.getTextureRect().height / 2.f);
- mSpriteWorld.setPosition(WINDOW_SIZE.x / 2.f, WINDOW_SIZE.y / 2.f);
- mShader.load(Shaders::Light, shaderCode, sf::Shader::Fragment);
- mShader.get(Shaders::Light).setUniform("ScreenResolution", sf::Vector2f(WINDOW_SIZE.x * 1.f, WINDOW_SIZE.y * 1.f));
- mShader.get(Shaders::Light).setUniform("LightAttenuation", 20.0f);
- }
- void World::draw()
- {
- if (PostEffect::isSupported())
- {
- mRenderTexture.clear();
- for (const auto& tile : mTiles)
- {
- mRenderTexture.draw(tile);
- sf::Vector2f position(tile.getPosition().x + tile.getLocalBounds().width / 2, tile.getPosition().y + tile.getLocalBounds().height / 2);
- auto& shader = mShader.get(Shaders::Light);
- shader.setUniform("LightOrigin", position);
- shader.setUniform("SourceColor", tile.getLightColor());
- sf::RenderStates states;
- states.shader = &shader;
- states.blendMode = sf::BlendAdd;
- mRenderTexture.draw(mSpriteWorld, states);
- }
- mRenderTexture.display();
- mTarget.clear();
- mTarget.draw(mSpriteWorld);
- mBloomEffect.apply(mRenderTexture, mTarget);
- }
- else
- {
- for (const auto& tile : mTiles)
- {
- mTarget.draw(tile);
- }
- }
- }
- bool World::applyMove(Player player, sf::Uint32 row, sf::Uint32 column) const
- {
- unsigned position = row + DIM * column;
- if ((position > mTiles.size()) || (mTiles[position].getOwner() != Player::None) || row >= DIM || column >= DIM)
- {
- return false;
- }
- --mRemain;
- mTiles[position].setOwner(player);
- switch (player)
- {
- case Player::User:
- mTiles[position].setLightColor(sf::Vector3f(0, 0, 255));
- break;
- case Player::Computer:
- mTiles[position].setLightColor(sf::Vector3f(255, 0, 0));
- break;
- }
- return true;
- }
- bool World::isFull() const
- {
- return (mRemain == 0);
- }
- bool World::applyAl(Player player) const
- {
- Move move = minimax();
- return applyMove(player, move.x, move.y);
- }
- World::Move World::minimax() const
- {
- int score = std::numeric_limits<int>::max();
- Move move;
- for (unsigned int i = 0; i < DIM; i++)
- {
- for (unsigned int j = 0; j < DIM; j++)
- {
- unsigned position = j * DIM + i;
- if (mTiles[position].getOwner() == Player::None)
- {
- mTiles[position].setOwner(Player::Computer);
- --mRemain;
- int temp = maxSearch(0);
- if (temp < score)
- {
- score = temp;
- move.x = i;
- move.y = j;
- }
- mTiles[position].setOwner(Player::None);
- ++mRemain;
- }
- }
- }
- return move;
- }
- int World::maxSearch(int level) const
- {
- if (isWinner(Player::User)) { return 10; }
- else if (isWinner(Player::Computer)) { return -10; }
- else if (isFull()) { return 0; }
- int score = std::numeric_limits<int>::min();
- for (unsigned int i = 0; i < DIM; i++)
- {
- for (unsigned int j = 0; j < DIM; j++)
- {
- unsigned position = j * DIM + i;
- if (mTiles[position].getOwner() == Player::None)
- {
- mTiles[position].setOwner(Player::User);
- --mRemain;
- score = std::max(score, minSearch(level + 1) - level);
- mTiles[position].setOwner(Player::None);
- ++mRemain;
- }
- }
- }
- return score;
- }
- int World::minSearch(int level) const
- {
- if (isWinner(Player::User)) { return 10; }
- else if (isWinner(Player::Computer)) { return -10; }
- else if (isFull()) { return 0; }
- int score = std::numeric_limits<int>::max();
- for (unsigned int i = 0; i < DIM; i++)
- {
- for (unsigned int j = 0; j < DIM; j++)
- {
- unsigned position = j * DIM + i;
- if (mTiles[position].getOwner() == Player::None)
- {
- mTiles[position].setOwner(Player::Computer);
- --mRemain;
- score = std::min(score, maxSearch(level + 1) + level);
- mTiles[position].setOwner(Player::None);
- ++mRemain;
- }
- }
- }
- return score;
- }
- bool World::isWinner(Player player) const
- {
- for (unsigned int i = 0; i < DIM; i++)
- {
- // Check horizontals
- if (mTiles[i].getOwner() == player &&
- mTiles[i + 3].getOwner() == player &&
- mTiles[i + 6].getOwner() == player)
- return true;
- // Check verticals
- if (mTiles[3 * i].getOwner() == player &&
- mTiles[1 + 3 * i].getOwner() == player &&
- mTiles[2 + 3 * i].getOwner() == player)
- return true;
- }
- // Check diagonals
- if (mTiles[0].getOwner() == player &&
- mTiles[4].getOwner() == player &&
- mTiles[8].getOwner() == player)
- return true;
- if (mTiles[6].getOwner() == player &&
- mTiles[4].getOwner() == player &&
- mTiles[2].getOwner() == player)
- return true;
- return false;
- }
- class Game : private sf::NonCopyable
- {
- public:
- Game();
- void run();
- private:
- void processEvents();
- void update();
- void render();
- sf::RenderWindow mWindow;
- FontHolder mFont;
- sf::Text mText;
- sf::Text mTitle;
- World mWorld;
- std::array<Player, NUMBER_OF_PLAYERS> mPlayers;
- unsigned mPlayer;
- };
- Game::Game()
- : mWindow(sf::VideoMode(WINDOW_SIZE.x, WINDOW_SIZE.y), "Tic Tac Toe - SFML")
- , mFont()
- , mText()
- , mTitle()
- , mWorld(mWindow)
- , mPlayers({ { Player::User, Player::Computer } })
- , mPlayer()
- {
- mWindow.setVerticalSyncEnabled(true);
- mFont.load(Fonts::Main, "Sansation.ttf");
- mText.setFont(mFont.get(Fonts::Main));
- mText.setStyle(sf::Text::Bold);
- mText.setCharacterSize(20);
- mText.setFillColor(sf::Color::White);
- mText.setPosition(30.f, mWindow.getSize().y - 50.f);
- centerOrigin(mText);
- mTitle.setString("Colourful Tic Tac Toe");
- mTitle.setFont(mFont.get(Fonts::Main));
- mTitle.setStyle(sf::Text::Bold);
- mTitle.setCharacterSize(30);
- mTitle.setFillColor(sf::Color::White);
- mTitle.setPosition(mWindow.getSize().x * 0.5f, 50.f);
- centerOrigin(mTitle);
- }
- void Game::run()
- {
- while (mWindow.isOpen())
- {
- processEvents();
- update();
- render();
- }
- }
- void Game::processEvents()
- {
- sf::Event event;
- while (mWindow.pollEvent(event))
- {
- if (event.type == sf::Event::Closed)
- mWindow.close();
- }
- }
- void Game::update()
- {
- static bool winner = false;
- if (winner)
- {
- mText.setString("The Winner: " + std::string((mPlayers[mPlayer] == Player::User) ? "Blues" : "Reds"));
- return;
- }
- if (mWorld.isFull())
- {
- mText.setString("*** Tie ***");
- return;
- }
- switch (mPlayers[mPlayer])
- {
- case Player::User:
- if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
- {
- sf::Vector2i position = sf::Mouse::getPosition(mWindow);
- if (position.x > START_POINT.x &&
- position.y > START_POINT.y &&
- position.x < (START_POINT.x + (DIM*SIZE)) &&
- position.y < (START_POINT.y + (DIM*SIZE)))
- {
- unsigned row = static_cast<unsigned>((position.y - START_POINT.y) / SIZE);
- unsigned col = static_cast<unsigned>((position.x - START_POINT.x) / SIZE);
- if (mWorld.applyMove(mPlayers[mPlayer], row, col)) {
- winner = mWorld.isWinner(mPlayers[mPlayer]);
- if (!winner) {
- mPlayer ^= 1;
- }
- }
- }
- }
- break;
- case Player::Computer:
- if (mWorld.applyAl(mPlayers[mPlayer])) {
- winner = mWorld.isWinner(mPlayers[mPlayer]);
- if (!winner) {
- mPlayer ^= 1;
- }
- }
- break;
- }
- }
- void Game::render()
- {
- mWindow.clear();
- mWorld.draw();
- mWindow.draw(mTitle);
- mWindow.draw(mText);
- mWindow.display();
- }
- int main()
- {
- try
- {
- Game game;
- game.run();
- }
- catch (std::runtime_error& e)
- {
- std::cout << "\nException: " << e.what() << std::endl;
- return 1;
- }
- }
Add Comment
Please, Sign In to add comment