diff --git a/Test/Test.vcxproj b/Test/Test.vcxproj new file mode 100644 index 0000000..8cf43da --- /dev/null +++ b/Test/Test.vcxproj @@ -0,0 +1,135 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {5CCBC659-08ED-4279-A5C4-6F16FB1FCC20} + Test + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + MultiThreaded + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + \ No newline at end of file diff --git a/Test/Test.vcxproj.filters b/Test/Test.vcxproj.filters new file mode 100644 index 0000000..32a8145 --- /dev/null +++ b/Test/Test.vcxproj.filters @@ -0,0 +1,25 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + + \ No newline at end of file diff --git a/Test/main.cpp b/Test/main.cpp new file mode 100644 index 0000000..d34662f --- /dev/null +++ b/Test/main.cpp @@ -0,0 +1,29 @@ +#include +#include + +int main(void) +{ + std::cout << "Start" << std::endl; + + sf::TcpSocket socket; + sf::Socket::Status status = socket.connect("93.201.163.184", 30000); + std::cout << "Verbindunsaufbau..." << std::endl; + if (status != sf::Socket::Done) { + std::cout << "Error while trying to connect to IP" << std::endl; + return 0; + } + + std::cout << "Bereit Verbindung aufzubauen" << std::endl; + char data[20]; + std::size_t received; + + if (socket.receive(data, 20, received) != sf::Socket::Done) { + std::cout << "Failed to receive package" << std::endl; + return 0; + } + + std::cout << data << std::endl; + getchar(); + + return 0; +} \ No newline at end of file diff --git a/Test/packages.config b/Test/packages.config new file mode 100644 index 0000000..a21dd09 --- /dev/null +++ b/Test/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Tic Tac Toe.sln b/Tic Tac Toe.sln new file mode 100644 index 0000000..c80de8c --- /dev/null +++ b/Tic Tac Toe.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tic Tac Toe", "Tic Tac Toe\Tic Tac Toe.vcxproj", "{271F58BA-B409-47FD-8EBE-D6202A17DAE6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {271F58BA-B409-47FD-8EBE-D6202A17DAE6}.Debug|x64.ActiveCfg = Debug|x64 + {271F58BA-B409-47FD-8EBE-D6202A17DAE6}.Debug|x64.Build.0 = Debug|x64 + {271F58BA-B409-47FD-8EBE-D6202A17DAE6}.Debug|x86.ActiveCfg = Debug|Win32 + {271F58BA-B409-47FD-8EBE-D6202A17DAE6}.Debug|x86.Build.0 = Debug|Win32 + {271F58BA-B409-47FD-8EBE-D6202A17DAE6}.Release|x64.ActiveCfg = Release|x64 + {271F58BA-B409-47FD-8EBE-D6202A17DAE6}.Release|x64.Build.0 = Release|x64 + {271F58BA-B409-47FD-8EBE-D6202A17DAE6}.Release|x86.ActiveCfg = Release|Win32 + {271F58BA-B409-47FD-8EBE-D6202A17DAE6}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Tic Tac Toe/Button.cpp b/Tic Tac Toe/Button.cpp new file mode 100644 index 0000000..74ad5c2 --- /dev/null +++ b/Tic Tac Toe/Button.cpp @@ -0,0 +1,78 @@ +#include "Button.hpp" + + +Button::Button(std::string text, int x, int y) +{ + default = ColorPalette(sf::Color(70, 70, 70), sf::Color(130, 130, 130), sf::Color(255, 255, 255)); + hover = ColorPalette(sf::Color(70, 70, 70), sf::Color(160, 160, 160), sf::Color(255, 255, 255)); + clicked = ColorPalette(sf::Color(130, 130, 130), sf::Color(70, 70, 70), sf::Color(255, 255, 255)); + disabled = ColorPalette(sf::Color(10, 10, 10), sf::Color(40, 40, 40), sf::Color(120, 120, 120)); + + background.setFillColor(default.background); + background.setOutlineColor(default.frame); + background.setOutlineThickness(15); + background.setSize(sf::Vector2f(400, 150)); + background.setPosition(sf::Vector2f(x, y)); + + font = new sf::Font(); + font->loadFromFile("C:/Windows/Fonts/lucon.ttf"); + + label.setFont(*font); + label.setColor(default.label); + label.setCharacterSize(48); + label.setString(text); + label.setOrigin(sf::Vector2f(label.getLocalBounds().width / 2, label.getLocalBounds().height)); + label.setPosition(sf::Vector2f(background.getGlobalBounds().left + background.getLocalBounds().width / 2, + background.getGlobalBounds().top + background.getLocalBounds().height / 2)); + + isDisabled = false; +} + +void Button::Update(int mouseX, int mouseY) +{ + if (mouseX > background.getGlobalBounds().left && mouseX < background.getGlobalBounds().left + background.getLocalBounds().width && + mouseY > background.getGlobalBounds().top && mouseY < background.getGlobalBounds().top + background.getLocalBounds().height) + { + background.setFillColor(hover.background); + background.setOutlineColor(hover.frame); + label.setFillColor(hover.label); + + } + + else + { + background.setFillColor(default.background); + background.setOutlineColor(default.frame); + label.setFillColor(default.label); + } + + if (isDisabled) + { + background.setFillColor(disabled.background); + background.setOutlineColor(disabled.frame); + label.setFillColor(disabled.label); + } +} + +void Button::Render(sf::RenderWindow& target) +{ + target.draw(background); + target.draw(label); +} + +bool Button::isClicked(int mouseX, int mouseY) +{ + if (isDisabled) return false; + + if (mouseX > background.getGlobalBounds().left && mouseX < background.getGlobalBounds().left + background.getLocalBounds().width && + mouseY > background.getGlobalBounds().top && mouseY < background.getGlobalBounds().top + background.getLocalBounds().height) + { + background.setFillColor(default.background); + background.setOutlineColor(default.frame); + label.setFillColor(default.label); + + return true; + } + + return false; +} diff --git a/Tic Tac Toe/Button.hpp b/Tic Tac Toe/Button.hpp new file mode 100644 index 0000000..168f8c6 --- /dev/null +++ b/Tic Tac Toe/Button.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +#include "Util.h" + +struct ColorPalette +{ + ColorPalette() {} + ColorPalette(sf::Color _frame, sf::Color _background, sf::Color _label) + { + frame = _frame; + background = _background; + label = _label; + } + + sf::Color frame, background, label; +}; + +class Button +{ +public: + Button() {} + Button(std::string text, int x, int y); + + void Update(int mouseX, int mouseY); + void Render(sf::RenderWindow& target); + + bool isClicked(int mouseX, int mouseY); + void disable() { + isDisabled = true; + } + void enable() + { + isDisabled = false; + } + +private: + sf::RectangleShape background; + sf::Text label; + sf::Font* font; + + ColorPalette default, hover, clicked, disabled; + + bool isDisabled; +}; \ No newline at end of file diff --git a/Tic Tac Toe/Field.cpp b/Tic Tac Toe/Field.cpp new file mode 100644 index 0000000..0690722 --- /dev/null +++ b/Tic Tac Toe/Field.cpp @@ -0,0 +1,130 @@ +#include "Field.hpp" + +#include + +Field::Field() +{ + tiles[0] = new Tile(50, 50); + tiles[1] = new Tile(300, 50); + tiles[2] = new Tile(550, 50); + tiles[3] = new Tile(50, 300); + tiles[4] = new Tile(300, 300); + tiles[5] = new Tile(550, 300); + tiles[6] = new Tile(50, 550); + tiles[7] = new Tile(300, 550); + tiles[8] = new Tile(550, 550); + + for (int i = 0; i < 4; i++) + { + lines[i].setFillColor(sf::Color(170, 170, 170)); + } + + lines[0].setPosition(250, 50); + lines[0].setSize(sf::Vector2f(50, 700)); + + lines[1].setPosition(500, 50); + lines[1].setSize(sf::Vector2f(50, 700)); + + lines[2].setPosition(50, 250); + lines[2].setSize(sf::Vector2f(700, 50)); + + lines[3].setPosition(50, 500); + lines[3].setSize(sf::Vector2f(700, 50)); +} + +char Field::Update() +{ + if (tiles[0]->what() == 'x' && tiles[1]->what() == 'x' && tiles[2]->what() == 'x') + return 'x'; + if (tiles[0]->what() == 'o' && tiles[1]->what() == 'o' && tiles[2]->what() == 'o') + return 'o'; + + if (tiles[3]->what() == 'x' && tiles[4]->what() == 'x' && tiles[5]->what() == 'x') + return 'x'; + if (tiles[3]->what() == 'o' && tiles[4]->what() == 'o' && tiles[5]->what() == 'o') + return 'o'; + + if (tiles[6]->what() == 'x' && tiles[7]->what() == 'x' && tiles[8]->what() == 'x') + return 'x'; + if (tiles[6]->what() == 'o' && tiles[7]->what() == 'o' && tiles[8]->what() == 'o') + return 'o'; + + + + + if (tiles[0]->what() == 'x' && tiles[3]->what() == 'x' && tiles[6]->what() == 'x') + return 'x'; + if (tiles[0]->what() == 'o' && tiles[3]->what() == 'o' && tiles[6]->what() == 'o') + return 'o'; + + if (tiles[1]->what() == 'x' && tiles[4]->what() == 'x' && tiles[7]->what() == 'x') + return 'x'; + if (tiles[1]->what() == 'o' && tiles[4]->what() == 'o' && tiles[7]->what() == 'o') + return 'o'; + + if (tiles[2]->what() == 'x' && tiles[5]->what() == 'x' && tiles[8]->what() == 'x') + return 'x'; + if (tiles[2]->what() == 'o' && tiles[5]->what() == 'o' && tiles[8]->what() == 'o') + return 'o'; + + + + + if (tiles[0]->what() == 'x' && tiles[4]->what() == 'x' && tiles[8]->what() == 'x') + return 'x'; + if (tiles[0]->what() == 'o' && tiles[4]->what() == 'o' && tiles[8]->what() == 'o') + return 'o'; + + if (tiles[2]->what() == 'x' && tiles[4]->what() == 'x' && tiles[6]->what() == 'x') + return 'x'; + if (tiles[2]->what() == 'o' && tiles[4]->what() == 'o' && tiles[6]->what() == 'o') + return 'o'; + + bool tied = true; + for (int i = 0; i < 9; i++) + if (tiles[i]->what() == ' ') + tied = false; + + if (tied) return 't'; + + return ' '; +} + + +bool Field::Click(int mouseX, int mouseY, char turn) +{ + for (int i = 0; i < 9; i++) + { + if (tiles[i]->what() == ' ') + { + if (tiles[i]->isClicked(mouseX, mouseY)) + { + //printf("Clicked Tile %i", i); + + sf::Vector2f pos = tiles[i]->getPosition(); + if (turn == 'x') + tiles[i] = new Cross(pos.x, pos.y); + else + tiles[i] = new Circle(pos.x, pos.y); + + return true; + } + } + //else { + // std::cout << "Mein Schwanz hurtet" << std::endl; + //} + } + + return false; +} + +void Field::Render(sf::RenderWindow& target) +{ + for (int i = 0; i < 4; i++) + target.draw(lines[i]); + + for (int i = 0; i < 9; i++) + tiles[i]->Render(target); + + // std::cout << std::endl; +} \ No newline at end of file diff --git a/Tic Tac Toe/Field.hpp b/Tic Tac Toe/Field.hpp new file mode 100644 index 0000000..3dff9b7 --- /dev/null +++ b/Tic Tac Toe/Field.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include "Tile.hpp" + +class Field +{ +public: + Field(); + + void Render(sf::RenderWindow& target); + char Update(); + bool Click(int mouseX, int mouseY, char turn); + +private: + sf::RectangleShape lines[4]; + Tile* tiles[9]; +}; + diff --git a/Tic Tac Toe/Framework.cpp b/Tic Tac Toe/Framework.cpp new file mode 100644 index 0000000..f7ea6ef --- /dev/null +++ b/Tic Tac Toe/Framework.cpp @@ -0,0 +1,540 @@ +#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(); +} \ No newline at end of file diff --git a/Tic Tac Toe/Framework.hpp b/Tic Tac Toe/Framework.hpp new file mode 100644 index 0000000..db6840d --- /dev/null +++ b/Tic Tac Toe/Framework.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include + +#include "Button.hpp" +#include "InputField.hpp" +#include "Field.hpp" +#include "Tile.hpp" +#include "Util.h" + +typedef unsigned short uint; + +struct Packet +{ + int mouseX, mouseY; + bool winCondition; +}; + +class Framework +{ +public: + Framework(uint width, uint height, std::string title); + ~Framework(); + + bool Run(); + +private: + bool HandleEvents(); + bool Update(); + bool Render(); + + void CalculateFrametime(); + + bool HostGame(); + bool JoinGame(); + + void StartGame(); + + void printInfo(int x, int y, char turn); + +private: + sf::RenderWindow* m_window; + sf::Event m_event; + sf::Clock m_clock; + + uint m_width; + uint m_height; + std::string m_title; + + Button m_host, m_join, m_newGame; + InputField m_ipField; + Field m_field; + + sf::IpAddress m_ip; + + GameState m_gameState; + Role m_role; + + sf::TcpListener listener; + sf::TcpSocket socket; + + sf::Text turn; + sf::Text winner; + sf::Font* font; + + std::default_random_engine engine; + std::uniform_int_distribution range; + + bool m_packageReceived; + bool m_connected; + bool m_myTurn; + char m_winner; + char m_mySymbol; + bool m_ready, m_otherReady; + + long double m_frametime; +}; + diff --git a/Tic Tac Toe/InputField.cpp b/Tic Tac Toe/InputField.cpp new file mode 100644 index 0000000..4a63e48 --- /dev/null +++ b/Tic Tac Toe/InputField.cpp @@ -0,0 +1,63 @@ +#include "InputField.hpp" + + + +InputField::InputField() +{ + value = ""; + + font = new sf::Font(); + font->loadFromFile("C:/Windows/Fonts/lucon.ttf"); + + field.setFillColor(sf::Color(10, 10, 10)); + field.setOutlineThickness(5); + field.setOutlineColor(sf::Color(60, 60, 60)); + field.setSize(sf::Vector2f(450, 50)); + field.setPosition(sf::Vector2f(250, 350)); + + input.setFont(*font); + input.setString(value); + input.setCharacterSize(32); + input.setPosition(sf::Vector2f(260, 350)); + + info.setFont(*font); + info.setString("Enter IP:"); + info.setCharacterSize(32); + info.setPosition(sf::Vector2f(50, 350)); +} + + +InputField::~InputField() +{ +} + +void InputField::updateText() +{ + input.setString(value); +} + +void InputField::Type(char letter) +{ + value += letter; + updateText(); +} + +std::string InputField::Enter() +{ + return value; +} + +void InputField::Backspace() +{ + if(value != "") + value.pop_back(); + + updateText(); +} + +void InputField::Render(sf::RenderWindow& target) +{ + target.draw(field); + target.draw(input); + target.draw(info); +} diff --git a/Tic Tac Toe/InputField.hpp b/Tic Tac Toe/InputField.hpp new file mode 100644 index 0000000..961d892 --- /dev/null +++ b/Tic Tac Toe/InputField.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +class InputField +{ +public: + InputField(); + ~InputField(); + + void Type(char letter); + std::string Enter(); + void Backspace(); + + void Render(sf::RenderWindow& target); + +private: + void updateText(); + + std::string value; + + sf::Text info; + sf::Text input; + sf::Font* font; + + sf::RectangleShape field; +}; + diff --git a/Tic Tac Toe/Tic Tac Toe.vcxproj b/Tic Tac Toe/Tic Tac Toe.vcxproj new file mode 100644 index 0000000..83eeeb5 --- /dev/null +++ b/Tic Tac Toe/Tic Tac Toe.vcxproj @@ -0,0 +1,191 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {271F58BA-B409-47FD-8EBE-D6202A17DAE6} + Win32Proj + TicTacToe + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + \ No newline at end of file diff --git a/Tic Tac Toe/Tic Tac Toe.vcxproj.filters b/Tic Tac Toe/Tic Tac Toe.vcxproj.filters new file mode 100644 index 0000000..fecb67a --- /dev/null +++ b/Tic Tac Toe/Tic Tac Toe.vcxproj.filters @@ -0,0 +1,66 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {17b14c9e-62d8-40e8-888e-f41312f89b60} + + + {f29d80d9-034f-463e-b7fc-a5979facd64d} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files\GUI + + + Source Files\GUI + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files\GUI + + + Header Files + + + Header Files\GUI + + + Header Files + + + + + + \ No newline at end of file diff --git a/Tic Tac Toe/Tile.cpp b/Tic Tac Toe/Tile.cpp new file mode 100644 index 0000000..191210d --- /dev/null +++ b/Tic Tac Toe/Tile.cpp @@ -0,0 +1,101 @@ +#include "Tile.hpp" + +#include + +Tile::Tile() +{ +} + +Tile::Tile(int posX, int posY) +{ + size = sf::Vector2f(200, 200); + active = false; + + position = sf::Vector2f(posX, posY); + + frame.setFillColor(sf::Color::Black); + frame.setOutlineThickness(-5); + frame.setOutlineColor(sf::Color::Green); + frame.setSize(size); + frame.setPosition(position); +} + + +Tile::~Tile() +{ +} + +bool Tile::isClicked(int mouseX, int mouseY) +{ + if (mouseX > position.x && mouseX < position.x + size.x && mouseY > position.y && mouseY < position.y + size.y) + return true; + + return false; +} + +void Tile::Render(sf::RenderWindow& target) +{ + // target.draw(frame); +} + + + +Cross::Cross() +{ + +} + +Cross::Cross(int posX, int posY) : + Tile(posX, posY) +{ + for (int i = 0; i < 2; i++) + { + lines[i].setFillColor(sf::Color(255, 50, 50)); + lines[i].setSize(sf::Vector2f(180, 10)); + lines[i].setOrigin(sf::Vector2f(lines[i].getGlobalBounds().left + lines[i].getLocalBounds().width / 2, + lines[i].getGlobalBounds().top + lines[i].getLocalBounds().height / 2)); + lines[i].setPosition(posX + 100, posY + 100); + + } + + lines[0].rotate(45); + lines[1].rotate(-45); +} + +void Cross::Render(sf::RenderWindow& target) +{ + Tile::Render(target); + + target.draw(lines[0]); + target.draw(lines[1]); +} + + + + + + + +Circle::Circle() +{ + +} + +Circle::Circle(int posX, int posY) : + Tile(posX, posY) +{ + cir.setRadius(90); + cir.setOutlineThickness(-10); + cir.setOutlineColor(sf::Color(10, 10, 255)); + cir.setOrigin(sf::Vector2f(cir.getGlobalBounds().left + cir.getLocalBounds().width / 2, + cir.getGlobalBounds().top + cir.getLocalBounds().height / 2)); + cir.setPosition(posX + 100, posY + 100); + cir.setFillColor(sf::Color::Black); +} + +void Circle::Render(sf::RenderWindow& target) +{ + Tile::Render(target); + + target.draw(cir); +} \ No newline at end of file diff --git a/Tic Tac Toe/Tile.hpp b/Tic Tac Toe/Tile.hpp new file mode 100644 index 0000000..63ca1c6 --- /dev/null +++ b/Tic Tac Toe/Tile.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include + +class Tile +{ +public: + Tile(); + Tile(int posX, int posY); + ~Tile(); + + virtual void Render(sf::RenderWindow& target); + virtual char what() { return ' '; } + bool isClicked(int mouseX, int mouseY); + + bool isActive() { return active; } + + sf::Vector2f getPosition() { return position; } + +private: + bool active; + + sf::RectangleShape frame; + +protected: + sf::Vector2f position; + sf::Vector2f size; +}; + + + +class Cross : public Tile +{ +public: + Cross(); + Cross(int posX, int posY); + + void Render(sf::RenderWindow& target) override; + char what() { return 'x'; } + +private: + sf::RectangleShape lines[2]; +}; + + +class Circle : public Tile +{ +public: + Circle(); + Circle(int posX, int posY); + + void Render(sf::RenderWindow& target) override; + char what() { return 'o'; } + +private: + sf::CircleShape cir; +}; \ No newline at end of file diff --git a/Tic Tac Toe/Util.h b/Tic Tac Toe/Util.h new file mode 100644 index 0000000..e14597c --- /dev/null +++ b/Tic Tac Toe/Util.h @@ -0,0 +1,19 @@ +#pragma once + +enum GameState +{ + MAIN_MENU, + READY, + IN_GAME, + GAME_OVER, + HOST_GAME, + JOIN_GAME, + CONNECTING +}; + +enum Role +{ + UNKNOWN, + HOST, + CLIENT +}; \ No newline at end of file diff --git a/Tic Tac Toe/main.cpp b/Tic Tac Toe/main.cpp new file mode 100644 index 0000000..8db8999 --- /dev/null +++ b/Tic Tac Toe/main.cpp @@ -0,0 +1,20 @@ +#include +#include +#include "Framework.hpp" + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nShowCmd) +{ + Framework frmwrk(800, 800, "Tic Tac Toe, x64"); + + if (!frmwrk.Run()) + { + std::cerr << "Runtime Error." << std::endl; + return 1; + } + + + return 0; +} \ No newline at end of file diff --git a/Tic Tac Toe/packages.config b/Tic Tac Toe/packages.config new file mode 100644 index 0000000..3468d45 --- /dev/null +++ b/Tic Tac Toe/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file