#include "Framework.hpp" #include #include Framework::Framework(uint width, uint height, std::string title) { font = new sf::Font(); font->loadFromFile("C:/Windows/Fonts/lucon.ttf"); turn.setFont(*font); turn.setString("Opponent's Turn"); turn.setCharacterSize(18); turn.setPosition(10, 10); turn.setFillColor(sf::Color::White); winner.setFont(*font); winner.setString("Placeholder"); winner.setCharacterSize(140); winner.setStyle(sf::Text::Style::Bold); winner.setPosition(100, 100); winner.setFillColor(sf::Color(10, 255, 10)); m_width = width; m_height = height; m_title = title; m_window = new sf::RenderWindow(sf::VideoMode(width, height), title, sf::Style::Close); m_window->setFramerateLimit(120); m_event = sf::Event(); m_clock = sf::Clock(); m_frametime = -1.0; m_gameState = MAIN_MENU; m_role = UNKNOWN; m_host = Button("Host Game", 200, 200); m_join = Button("Join Game", 200, 450); m_newGame = Button("New Game", 200, 450); m_ipField = InputField(); m_field = Field(); m_winner = ' '; m_ip = ""; m_connected = false; m_packageReceived = false; m_myTurn = false; m_mySymbol = 'o'; m_ready = true; m_otherReady = true; listener.setBlocking(false); engine = std::default_random_engine{ static_cast(time(0)) }; range = std::uniform_int_distribution(0, 1); m_clock.restart(); } Framework::~Framework() { delete m_window; m_window = nullptr; } bool Framework::Run() { if (m_window == nullptr) { std::cerr << "Framework was not initialized." << std::endl; return false; } while (m_window->isOpen()) { if (!HandleEvents()) return false; if (!Update()) return false; if (!Render()) return false; } return true; } void Framework::StartGame() { m_gameState = IN_GAME; // If host, determine who begins. // if client, wait for host to call who begins // If it is host's turn -> Let Host make turn, send client turn result // If it is client's turn -> Let client make turn, send host turn result } bool Framework::HostGame() { if (!m_connected) { m_role = HOST; sf::Font font; font.loadFromFile("C:/Windows/Fonts/lucon.ttf"); sf::Text text; text.setFont(font); text.setCharacterSize(48); text.setFillColor(sf::Color::White); text.setString("Waiting for connection..."); text.setOrigin(text.getLocalBounds().left + text.getLocalBounds().width / 2, text.getLocalBounds().top + text.getLocalBounds().height / 2); text.setPosition(sf::Vector2f(400, 400)); sf::Text ip; ip.setFont(font); ip.setCharacterSize(24); ip.setFillColor(sf::Color::White); ip.setString("Your IP: " + m_ip.getPublicAddress().toString()); ip.setOrigin(ip.getLocalBounds().left + ip.getLocalBounds().width / 2, ip.getLocalBounds().top + ip.getLocalBounds().height / 2); ip.setPosition(sf::Vector2f(400, 550)); m_window->draw(text); m_window->draw(ip); if (listener.accept(socket) == sf::Socket::Done) { m_connected = true; m_gameState = READY; socket.setBlocking(false); } return true; } else { if (m_gameState == READY) { int starter = range(engine); std::cout << starter << std::endl; /*LPCWSTR who = L"Nobody"; if (starter == true) { who = L"Opponent"; } if (starter != true) { who = L"My turn"; }*/ // MessageBox(NULL, who, L"Host", MB_OK); sf::Packet data; data << starter; if (socket.send(data) == sf::Socket::Done) { m_gameState = IN_GAME; if (starter == 0) { m_myTurn = true; m_mySymbol = 'x'; turn.setString("Your Turn"); } else { m_myTurn = false; m_mySymbol = 'o'; turn.setString("Opponent's Turn"); } } } if (m_gameState == IN_GAME) { // If not my turn, wait for package sf::Packet data; if (socket.receive(data) == sf::Socket::Done) { m_myTurn = true; turn.setString("Your Turn"); int mouseX, mouseY; int symb; data >> mouseX >> mouseY >> symb; m_field.Click(mouseX, mouseY, (char)symb); printInfo(mouseX, mouseY, (char)symb); } } if (m_gameState == GAME_OVER) { sf::Packet data; if (socket.receive(data) == sf::Socket::Done) { m_otherReady = true; } } } return true; } void Framework::printInfo(int x, int y, char turn) { // std::cout << turn << " set piece at (" << x << ", " << y << ")" << std::endl; } bool Framework::JoinGame() { if (!m_connected) { m_role = CLIENT; if (socket.connect(m_ip, 30000, sf::Time(sf::seconds(3))) != sf::Socket::Done) { std::cerr << "Could not connect to " << m_ip << ":30000. Is the IP correct and port 30000 open on the host's PC?" << std::endl; return false; } socket.setBlocking(false); m_connected = true; m_gameState = READY; return true; } else { if (m_gameState == READY) { m_winner = ' '; // Wait for Host to send data about who starts sf::Packet data; if (socket.receive(data) == sf::Socket::Done) { m_gameState = IN_GAME; int starter; data >> starter; //LPCWSTR who = (starter) ? L"Me" : L"Other"; //MessageBox(NULL, who, L"Client", MB_OK); std::cout << starter << std::endl; if (starter == true) { m_myTurn = true; m_mySymbol = 'x'; turn.setString("Your Turn"); } else { m_myTurn = false; m_mySymbol = 'o'; turn.setString("Opponent's Turn"); } } } if (m_gameState == IN_GAME) { // If not my turn, wait for package sf::Packet data; if (socket.receive(data) == sf::Socket::Done) { m_myTurn = true; turn.setString("Your Turn"); int mouseX, mouseY; int symb; data >> mouseX >> mouseY >> symb; m_field.Click(mouseX, mouseY, (char)symb); printInfo(mouseX, mouseY, (char)symb); } } if (m_gameState == GAME_OVER) { sf::Packet data; if (socket.receive(data) == sf::Socket::Done) { m_gameState = READY; m_field = Field(); m_newGame.enable(); } } } return true; } bool Framework::HandleEvents() { while (m_window->pollEvent(m_event)) { switch (m_event.type) { case sf::Event::Closed: m_window->close(); break; case sf::Event::MouseButtonReleased: { if (m_gameState == MAIN_MENU) { if (m_host.isClicked(sf::Mouse::getPosition(*m_window).x, sf::Mouse::getPosition(*m_window).y)) { m_gameState = CONNECTING; m_role = HOST; if (listener.listen(30000) != sf::Socket::Done) { std::cerr << "Could not listen for incoming requests at port 30000" << std::endl; return false; } } if (m_join.isClicked(sf::Mouse::getPosition(*m_window).x, sf::Mouse::getPosition(*m_window).y)) { m_gameState = JOIN_GAME; } } if (m_gameState == IN_GAME && m_myTurn) { if (!m_field.Click(sf::Mouse::getPosition(*m_window).x, sf::Mouse::getPosition(*m_window).y, m_mySymbol)) break; m_myTurn = false; turn.setString("Opponent's Turn"); sf::Packet data; data << sf::Mouse::getPosition(*m_window).x << sf::Mouse::getPosition(*m_window).y << m_mySymbol; socket.send(data); } if (m_gameState == GAME_OVER) { if (m_newGame.isClicked(sf::Mouse::getPosition(*m_window).x, sf::Mouse::getPosition(*m_window).y)) { if (m_role == HOST) { m_ready = true; m_newGame.disable(); } if (m_role == CLIENT) { m_newGame.disable(); sf::Packet data; data << true; if (socket.send(data) == sf::Socket::Done) break; } } } } break; case sf::Event::KeyPressed: { if (m_gameState == JOIN_GAME) { if (m_event.key.code == sf::Keyboard::Return) { m_ip = sf::IpAddress(m_ipField.Enter()); m_role = CLIENT; m_gameState = CONNECTING; } if (m_event.key.code == sf::Keyboard::BackSpace) m_ipField.Backspace(); if (m_event.key.code == sf::Keyboard::Period) m_ipField.Type('.'); for (int key = sf::Keyboard::Num0; key <= sf::Keyboard::Num9; key++) { if(m_event.key.code == key) m_ipField.Type(key + 22); } } } break; default: break; } } return true; } bool Framework::Update() { m_window->clear(sf::Color::Black); CalculateFrametime(); int FPS = floor(1 / m_frametime); m_window->setTitle(m_title + " | " + std::to_string(FPS) + " FPS"); int mouseX = sf::Mouse::getPosition(*m_window).x; int mouseY = sf::Mouse::getPosition(*m_window).y; if (m_gameState == MAIN_MENU) { m_host.Update(mouseX, mouseY); m_join.Update(mouseX, mouseY); } if (m_gameState == IN_GAME || m_gameState == READY || m_gameState == GAME_OVER || m_gameState == CONNECTING) { if (m_role == HOST) HostGame(); if (m_role == CLIENT) JoinGame(); } if (m_gameState == GAME_OVER) { m_myTurn = false; if (m_winner == m_mySymbol) { winner.setString("You won!"); winner.setOrigin(winner.getLocalBounds().left + winner.getLocalBounds().width / 2, winner.getLocalBounds().top + winner.getLocalBounds().height / 2); winner.setPosition(m_window->getSize().x / 2, m_window->getSize().y / 4); } if (m_winner != m_mySymbol) { if (m_winner == 't') { winner.setString("Tie!"); winner.setOrigin(winner.getLocalBounds().left + winner.getLocalBounds().width / 2, winner.getLocalBounds().top + winner.getLocalBounds().height / 2); winner.setPosition(m_window->getSize().x / 2, m_window->getSize().y / 4); } else { winner.setString("You lost!"); winner.setOrigin(winner.getLocalBounds().left + winner.getLocalBounds().width / 2, winner.getLocalBounds().top + winner.getLocalBounds().height / 2); winner.setPosition(m_window->getSize().x / 2, m_window->getSize().y / 4); } } m_newGame.Update(mouseX, mouseY); if (m_ready && m_otherReady) { m_gameState = READY; m_ready = false; m_otherReady = false; m_field = Field(); m_newGame.enable(); sf::Packet data; data << true; socket.send(data) == sf::Socket::Done; } // std::cout << "Host: " << m_ready << std::endl << "Client: " << m_otherReady << std::endl << std::endl; } if (m_gameState != GAME_OVER) { m_winner = m_field.Update(); if (m_winner != ' ') { m_gameState = GAME_OVER; m_ready = false; m_otherReady = false; } } return true; } bool Framework::Render() { if (m_gameState == MAIN_MENU) { m_host.Render(*m_window); m_join.Render(*m_window); } if (m_gameState == JOIN_GAME) { m_ipField.Render(*m_window); } if (m_gameState == IN_GAME || m_gameState == GAME_OVER) { m_field.Render(*m_window); m_window->draw(turn); } if (m_gameState == GAME_OVER) { m_window->draw(winner); m_newGame.Render(*m_window); } m_window->display(); return true; } void Framework::CalculateFrametime() { m_frametime = m_clock.getElapsedTime().asSeconds(); m_clock.restart(); }