game engine implementation, rendering tasks offloaded to Board from Game
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
# EN: The following is a list of files/catalogues, which should be ommited from commiting to the git repository.
|
# EN: The following is a list of files/catalogues, which should be ommited from commiting to the git repository.
|
||||||
# PL: W tym pliku zawarta została lista plików/ścieżek, które powinny zostać pominięte w commitach do repozytorium git.
|
# PL: W tym pliku zawarta została lista plików/ścieżek, które powinny zostać pominięte w commitach do repozytorium git.
|
||||||
|
Chinczyk188/.tablica_wynikow.csv.old
|
||||||
|
|
||||||
# EN: Visual Studio-related directories.
|
# EN: Visual Studio-related directories.
|
||||||
# PL: Katalogi związane z Visual Studio.
|
# PL: Katalogi związane z Visual Studio.
|
||||||
|
|||||||
177
Chinczyk188/Board.cpp
Normal file
177
Chinczyk188/Board.cpp
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#include "Board.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "Engine.hpp"
|
||||||
|
|
||||||
|
void Board::initVariables() {
|
||||||
|
|
||||||
|
// Ustaw wartości na domyślne.
|
||||||
|
this->window = nullptr;
|
||||||
|
|
||||||
|
// Wczytaj tło - bitmapę planszy.
|
||||||
|
// loadFromFile() zwraca True w przypadku pomyślnego
|
||||||
|
// wczytania tekstury.
|
||||||
|
if (!this->boardTexture.loadFromFile("res/sprites/board.png")) {
|
||||||
|
|
||||||
|
// Jeśli nie uda nam się wczytać tekstury:
|
||||||
|
std::cerr << "Uwaga: Nie udalo sie wczytac "
|
||||||
|
"wymaganej tekstury planszy z \"res/sprites/board.png\"!\n"
|
||||||
|
"Upewnij sie, ze plik .exe jest we wlasciwym katalogu, "
|
||||||
|
"a gra zostala w pelni wypakowana wraz z folderem \"res\".\n";
|
||||||
|
|
||||||
|
sf::sleep(sf::seconds(10));
|
||||||
|
this->window->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::initWindow() {
|
||||||
|
|
||||||
|
// Dwuwymiarowy, wektor typu (u)nsigned int.
|
||||||
|
sf::Vector2u textureSize = this->boardTexture.getSize();
|
||||||
|
|
||||||
|
// Aby okno zmieściło się na większości wyświetlaczy,
|
||||||
|
// sprawmy, aby zajmowało ono około 450x450 pikseli,
|
||||||
|
// czyli dokładnie połowę z rozdzielczości tekstury planszy.
|
||||||
|
this->videoMode.width = textureSize.x / 2;
|
||||||
|
this->videoMode.height = textureSize.y / 2;
|
||||||
|
|
||||||
|
// Stwórz okno.
|
||||||
|
this->window = new sf::RenderWindow(
|
||||||
|
this->videoMode,
|
||||||
|
"Okno planszy - Chinczyk188",
|
||||||
|
sf::Style::Default);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::initBoard() {
|
||||||
|
|
||||||
|
// Wczytaj wymaganą teksturę planszy
|
||||||
|
this->boardSprite.setTexture(this->boardTexture);
|
||||||
|
|
||||||
|
// Ustaw pozycję grafiki.
|
||||||
|
this->boardSprite.setPosition(0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::initView() {
|
||||||
|
|
||||||
|
// Ze względu na to, że długość krawędzi okna jest dwa razy mniejsza
|
||||||
|
// od tekstury planszy, powinniśmy to zrównoważyć powiększając
|
||||||
|
// widok o tą samą wartość.
|
||||||
|
sf::Vector2f viewSize(
|
||||||
|
static_cast<float>(2 * this->videoMode.width),
|
||||||
|
static_cast<float>(2 * this->videoMode.height)
|
||||||
|
);
|
||||||
|
|
||||||
|
this->view.setSize(viewSize);
|
||||||
|
this->view.setCenter(viewSize.x / 2.0f, viewSize.y / 2.0f);
|
||||||
|
|
||||||
|
// Ustawiamy widok na wyznaczone wartości.
|
||||||
|
this->window->setView(this->view);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::handleResize(unsigned int newWidth, unsigned int newHeight) {
|
||||||
|
|
||||||
|
// Aby zapobiec sytuacji, w której po zmianie rozmiaru
|
||||||
|
// okno byłoby większe od rozdzielczości ekranu,
|
||||||
|
// niech krawędź okna wynosi minimum z nowej szerokości i wysokości,
|
||||||
|
// zachowując przy tym proporcję 1:1 planszy.
|
||||||
|
unsigned int newSize = std::min(newWidth, newHeight);
|
||||||
|
this->window->setSize(sf::Vector2u(newSize, newSize));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Board::running() const {
|
||||||
|
|
||||||
|
// Akcesor dla isOpen()
|
||||||
|
return this->window->isOpen();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::pollEvents() {
|
||||||
|
|
||||||
|
while (this->window->pollEvent(this->ev)) {
|
||||||
|
|
||||||
|
switch (this->ev.type) {
|
||||||
|
|
||||||
|
case sf::Event::Closed:
|
||||||
|
this->window->close();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sf::Event::Resized:
|
||||||
|
this->handleResize(this->ev.size.width, this->ev.size.height);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sf::Event::KeyPressed:
|
||||||
|
if (this->ev.key.code == sf::Keyboard::Escape)
|
||||||
|
this->window->close();
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::update() {
|
||||||
|
|
||||||
|
// Obecnie wrapper dla metody
|
||||||
|
// pollEvents(), nasłuchiwanie wydarzeń.
|
||||||
|
this->pollEvents();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Board::manualUpdate() {
|
||||||
|
|
||||||
|
this->update();
|
||||||
|
this->render();
|
||||||
|
|
||||||
|
bool retval = this->window->pollEvent(this->ev);
|
||||||
|
this->lastEvent = this->ev;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::render() {
|
||||||
|
|
||||||
|
// Mechanizm renderowania
|
||||||
|
|
||||||
|
// Czyszczenie ekranu
|
||||||
|
this->window->clear(sf::Color::White);
|
||||||
|
// Rysowanie tła
|
||||||
|
this->window->draw(this->boardSprite);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Mechanizm wyświetlania
|
||||||
|
// W celu wyświetlenia na ekranie wyniku renderowania
|
||||||
|
this->window->display();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::updateAndRender() {
|
||||||
|
|
||||||
|
this->render();
|
||||||
|
this->update();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::runAsThread() {
|
||||||
|
|
||||||
|
//this->thread = std::thread([this]() {this->updateAndRender();});
|
||||||
|
//this->threads.push_back(std::thread([this]() { this->updateAndRender(); }));
|
||||||
|
// this->thread = std::thread(&Board::updateAndRender, this);
|
||||||
|
//this->threads.front().launch();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::closeWindow() {
|
||||||
|
|
||||||
|
this->window->close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::run() {
|
||||||
|
|
||||||
|
}
|
||||||
54
Chinczyk188/Board.hpp
Normal file
54
Chinczyk188/Board.hpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <SFML/System/Thread.hpp>
|
||||||
|
#include <SFML/Window/Event.hpp>
|
||||||
|
#include <thread>
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
|
class Board {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Wskaźnik na okno.
|
||||||
|
sf::RenderWindow* window;
|
||||||
|
sf::VideoMode videoMode;
|
||||||
|
|
||||||
|
sf::Texture boardTexture;
|
||||||
|
sf::Sprite boardSprite;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Aby przekazać je do Engine
|
||||||
|
sf::Event ev;
|
||||||
|
sf::View view;
|
||||||
|
|
||||||
|
// Konstruktor, destruktor
|
||||||
|
void closeWindow();
|
||||||
|
|
||||||
|
// Akcesor
|
||||||
|
bool running() const;
|
||||||
|
|
||||||
|
//Board(): thread(&Board::updateAndRender, this) {};
|
||||||
|
|
||||||
|
// Metody klasy
|
||||||
|
void pollEvents();
|
||||||
|
void update();
|
||||||
|
void render();
|
||||||
|
void updateAndRender();
|
||||||
|
void run();
|
||||||
|
bool manualUpdate();
|
||||||
|
sf::Event lastEvent;
|
||||||
|
//std::vector<std::thread> threads;
|
||||||
|
//std::vector<sf::Thread> threads;
|
||||||
|
//sf::Thread thread;
|
||||||
|
void runAsThread();
|
||||||
|
|
||||||
|
// Sterowanie oknem
|
||||||
|
void initVariables();
|
||||||
|
void initWindow();
|
||||||
|
void initBoard();
|
||||||
|
void initView();
|
||||||
|
void handleResize(unsigned int newWidth, unsigned int newHeight);
|
||||||
|
|
||||||
|
};
|
||||||
@@ -102,14 +102,16 @@
|
|||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>SFML_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;SFML_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)res\SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)res\SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>sfml-graphics-s-d.lib;opengl32.lib;freetype.lib;sfml-window-s-d.lib;winmm.lib;gdi32.lib;sfml-system-s-d.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>sfml-graphics-s-d.lib;opengl32.lib;freetype.lib;sfml-window-s-d.lib;winmm.lib;gdi32.lib;sfml-system-s-d.lib;sfml-audio-s-d.lib;openal32.lib;flac.lib;ogg.lib;vorbis.lib;vorbisenc.lib;vorbisfile.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>$(ProjectDir)res\SFML\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(ProjectDir)res\SFML\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@@ -119,21 +121,36 @@
|
|||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>SFML_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;SFML_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)res\SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)res\SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>sfml-graphics-s.lib;opengl32.lib;freetype.lib;sfml-window-s.lib;winmm.lib;gdi32.lib;sfml-system-s.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>sfml-graphics-s.lib;opengl32.lib;freetype.lib;sfml-window-s.lib;winmm.lib;gdi32.lib;sfml-system-s.lib;sfml-audio-s.lib;openal32.lib;flac.lib;ogg.lib;vorbis.lib;vorbisenc.lib;vorbisfile.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>$(ProjectDir)res\SFML\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(ProjectDir)res\SFML\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Board.cpp" />
|
||||||
|
<ClCompile Include="Engine.cpp" />
|
||||||
|
<ClCompile Include="Game.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="Pawn.cpp" />
|
||||||
|
<ClCompile Include="Player.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Board.hpp" />
|
||||||
|
<ClInclude Include="Engine.hpp" />
|
||||||
|
<ClInclude Include="Game.hpp" />
|
||||||
|
<ClInclude Include="Pawn.hpp" />
|
||||||
|
<ClInclude Include="Player.hpp" />
|
||||||
|
<ClInclude Include="ssp.hpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|||||||
@@ -18,5 +18,40 @@
|
|||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Game.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Engine.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Pawn.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Player.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Board.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Game.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ssp.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Engine.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Pawn.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Player.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Board.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
215
Chinczyk188/Engine.cpp
Normal file
215
Chinczyk188/Engine.cpp
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
#include "Engine.hpp"
|
||||||
|
#include <SFML/Graphics/RenderWindow.hpp>
|
||||||
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
#include <SFML/Window/Event.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
const char* colorNames[] = {"czerwony", "niebieski", "zolty", "zielony"};
|
||||||
|
|
||||||
|
Engine::Engine(): currentPlayerIndex(0) {
|
||||||
|
if (!this->dicerollBuffer.openFromFile("res/audio/wardoctor17_diceroll.ogg")) {
|
||||||
|
std::cerr << "Nie udalo sie zaladowac efektu dzwiekowego rzutu kostka.\n\n";
|
||||||
|
this->dicerollLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->pawnmoveBuffer.openFromFile("res/audio/PeteBarry_pawnmove.ogg")) {
|
||||||
|
std::cerr << "Nie udalo sie zaladowac efektu dzwiekowego ruchu pionkow.\n\n";
|
||||||
|
this->pawnmoveLoaded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::addPlayer(const std::string& name, unsigned int seed, short color) {
|
||||||
|
this->players.emplace_back(name, seed, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::initializeGame() {
|
||||||
|
int totalPawnsPerPlayer = 4; // 4 pionki na gracza
|
||||||
|
for (auto& player: players) {
|
||||||
|
player.initializePawns(totalPawnsPerPlayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::startGame(Board board) {
|
||||||
|
initializeGame();
|
||||||
|
this->board = board;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::nextTurn() {
|
||||||
|
|
||||||
|
this->turnCounter++;
|
||||||
|
std::cout << "-------------------- \n"
|
||||||
|
<< this->turnCounter << "\n"
|
||||||
|
<< "-------------------- \n";
|
||||||
|
|
||||||
|
Player& currentPlayer = players[currentPlayerIndex];
|
||||||
|
std::cout << "Ruch gracza " << currentPlayer.getName()
|
||||||
|
<< " (" << colorNames[currentPlayer.getColor()] << ").\n";
|
||||||
|
|
||||||
|
// Rzut kostką
|
||||||
|
if (dicerollLoaded) this->dicerollBuffer.play();
|
||||||
|
int diceRoll = rollDice(currentPlayer.getSeed(), currentPlayer.getRollCount());
|
||||||
|
std::cout << "Wylosowano " << diceRoll << ".\n";
|
||||||
|
currentPlayer.incrementRollCount();
|
||||||
|
sf::sleep(sf::milliseconds(1000));
|
||||||
|
|
||||||
|
// Wybieranie pionka
|
||||||
|
bool pickAPlace = false;
|
||||||
|
// Wylosowanie szóstki to specjalny przypadek
|
||||||
|
if (diceRoll == 6) {
|
||||||
|
if (currentPlayer.pawnsActive == 0) {
|
||||||
|
// Musi wyjść pionkiem
|
||||||
|
std::cout << currentPlayer.getName() << " wychodzi pierwszym pionkiem z bazy.\n";
|
||||||
|
currentPlayer.pawnsAtBase--;
|
||||||
|
currentPlayer.pawnsActive++;
|
||||||
|
this->pawnmoveBuffer.play();
|
||||||
|
sf::sleep(sf::milliseconds(2000));
|
||||||
|
} else if (currentPlayer.pawnsActive > 0 && currentPlayer.pawnsActive < 4) {
|
||||||
|
|
||||||
|
// Może wyjść z bazy albo ruszyć pionek
|
||||||
|
char choice;
|
||||||
|
|
||||||
|
std::cout << "Co chcesz zrobic?\n";
|
||||||
|
std::cout << "a) Wyjsc pionkiem z bazy\n"
|
||||||
|
<< "b) Wykonac ruch wyciagnietym wczesniej pionkiem\n"
|
||||||
|
<< "> ";
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
std::cin >> choice;
|
||||||
|
choice |= 32;
|
||||||
|
|
||||||
|
if (choice == 'a') {
|
||||||
|
|
||||||
|
pickAPlace = false;
|
||||||
|
std::cout << currentPlayer.getName() << " wychodzi "
|
||||||
|
<< currentPlayer.pawnsActive + 1 << ". pionkiem z bazy.\n";
|
||||||
|
currentPlayer.pawnsAtBase--;
|
||||||
|
currentPlayer.pawnsActive++;
|
||||||
|
this->pawnmoveBuffer.play();
|
||||||
|
sf::sleep(sf::milliseconds(2000));
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (choice == 'b') {
|
||||||
|
|
||||||
|
if (currentPlayer.pawnsActive > 1) {
|
||||||
|
pickAPlace = true;
|
||||||
|
} else {
|
||||||
|
std::cout << currentPlayer.getName() << " rusza jedyny pionek "
|
||||||
|
<< diceRoll << " pol do przodu.\n";
|
||||||
|
this->pawnmoveBuffer.play();
|
||||||
|
sf::sleep(sf::milliseconds(2000));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else std::cout << "Podaj jedna z wymienionych odpowiedzi!\n> ";
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (currentPlayer.pawnsActive == 4) {
|
||||||
|
// Musi ruszyć pionek, o ile może
|
||||||
|
// TODO
|
||||||
|
pickAPlace = true;
|
||||||
|
this->pawnmoveBuffer.play();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Musi ruszyć któryś z pionków
|
||||||
|
pickAPlace = true;
|
||||||
|
if (currentPlayer.pawnsActive == 1) {
|
||||||
|
// Jedyny pionek możemy ruszyć za niego
|
||||||
|
pickAPlace = false;
|
||||||
|
std::cout << currentPlayer.getName() << " rusza jedyny pionek "
|
||||||
|
<< diceRoll << " pol do przodu.\n";
|
||||||
|
this->pawnmoveBuffer.play();
|
||||||
|
sf::sleep(sf::milliseconds(2000));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPlayer.pawnsActive > 1 && pickAPlace) {
|
||||||
|
std::cout << "Wybierz prosze pionek na planszy ktorym chcesz wykonac ruch.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Użytkownik wybiera pionek na planszy, którym chce się ruszyć
|
||||||
|
int pickStatus = 0;
|
||||||
|
if (currentPlayer.pawnsActive == 0 || !pickAPlace) pickStatus = 8; // pomiń pętlę
|
||||||
|
while (pickStatus != 8) {
|
||||||
|
|
||||||
|
while (board.manualUpdate()) {
|
||||||
|
|
||||||
|
sf::Event currentEvent = board.lastEvent;
|
||||||
|
std::cout << "this-evtype: " << currentEvent.type << "\n";
|
||||||
|
switch (currentEvent.type) {
|
||||||
|
|
||||||
|
case sf::Event::Closed:
|
||||||
|
board.closeWindow();
|
||||||
|
// Zamknięcie okna powinno wyjść z tej pętli
|
||||||
|
pickStatus = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sf::Event::MouseButtonPressed:
|
||||||
|
std::cout << "pretend i'm selecting a piece\n";
|
||||||
|
pickStatus = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sf::Event::MouseButtonReleased:
|
||||||
|
std::cout << "pretend i'm releasing a piece\n";
|
||||||
|
this->pawnmoveBuffer.play();
|
||||||
|
sf::sleep(sf::seconds(1.0f));
|
||||||
|
if (pickStatus == 4) pickStatus = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sf::Event::Resized:
|
||||||
|
std::cout << "resized triggered: " << currentEvent.size.width << " " << currentEvent.size.height << "\n";
|
||||||
|
board.handleResize(currentEvent.size.width, currentEvent.size.height);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEST
|
||||||
|
// currentPlayer.tryMovingPawn(0, 0);
|
||||||
|
|
||||||
|
// if (!pickAPlace) {
|
||||||
|
// std::cout << "Brak ruchu.\n";
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (currentPlayer.hasWon()) {
|
||||||
|
// Zostanie wykorzystane do zwiększenia liczby wygranych
|
||||||
|
this->winnerNickname = currentPlayer.getName();
|
||||||
|
announceWinner(currentPlayer);
|
||||||
|
} else {
|
||||||
|
// Iteruj po wektorze z graczami
|
||||||
|
currentPlayerIndex = (currentPlayerIndex + 1) % players.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::sleep(sf::milliseconds(1000));
|
||||||
|
std::cout << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deterministycznie (lub nie) generuj kolejne rzuty kostką
|
||||||
|
int Engine::rollDice(unsigned int seed, unsigned int rollNumber) {
|
||||||
|
// Podane ziarno gracza oraz numer losowania zostaną użyte
|
||||||
|
// do wylosowania liczby od 1 do 6.
|
||||||
|
std::mt19937 rng(seed + rollNumber);
|
||||||
|
std::uniform_int_distribution<int> dist(1, 6);
|
||||||
|
|
||||||
|
return dist(rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Engine::isGameOver() const {
|
||||||
|
for (const auto& player: players) {
|
||||||
|
if (player.hasWon()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::announceWinner(const Player& player) const {
|
||||||
|
std::cout << "\n\n--------------------\n"
|
||||||
|
<< "Koniec gry!\n"
|
||||||
|
<< player.getName()
|
||||||
|
<< " (" << colorNames[player.getColor()] << ") wygrywa!\n";
|
||||||
|
}
|
||||||
47
Chinczyk188/Engine.hpp
Normal file
47
Chinczyk188/Engine.hpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Board.hpp"
|
||||||
|
#include "Player.hpp"
|
||||||
|
#include <SFML/Graphics/View.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <SFML/Audio/Music.hpp>
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
#include <SFML/Window/Event.hpp>
|
||||||
|
|
||||||
|
class Engine {
|
||||||
|
public:
|
||||||
|
Engine();
|
||||||
|
|
||||||
|
// Przygotowanie zmiennych
|
||||||
|
void addPlayer(const std::string& name, unsigned int seed, short color);
|
||||||
|
void initializeGame();
|
||||||
|
|
||||||
|
// Pętla gry
|
||||||
|
void startGame(Board board);
|
||||||
|
bool isGameOver() const;
|
||||||
|
|
||||||
|
// Logika gry
|
||||||
|
void nextTurn();
|
||||||
|
int rollDice(unsigned int seed, unsigned int moveNumber);
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
bool dicerollLoaded = true;
|
||||||
|
bool pawnmoveLoaded = true;
|
||||||
|
sf::Music dicerollBuffer;
|
||||||
|
sf::Music pawnmoveBuffer;
|
||||||
|
|
||||||
|
// Pomocnicze
|
||||||
|
std::string winnerNickname = "";
|
||||||
|
unsigned int turnCounter = 0;
|
||||||
|
|
||||||
|
// Z Game
|
||||||
|
Board board;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Player> players;
|
||||||
|
short currentPlayerIndex;
|
||||||
|
|
||||||
|
// Pomocnicze
|
||||||
|
void announceWinner(const Player& player) const;
|
||||||
|
};
|
||||||
@@ -1,71 +1,410 @@
|
|||||||
#include "Game.hpp"
|
#include "Game.hpp"
|
||||||
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem> // sprawdzenie, czy plik istnieje
|
||||||
|
#include "ssp.hpp" // nagłówkowy parser plików .csv
|
||||||
|
#include "Engine.hpp"
|
||||||
|
|
||||||
|
void Game::printGameWelcomeText() const {
|
||||||
|
|
||||||
|
std::cout << "\n"
|
||||||
|
" .o88b. db db d888888b d8b db .o88b. d88888D db db db dD db .d888b. .d888b.\n"
|
||||||
|
"d8P Y8 88 88 `88' 888o 88 d8P Y8 YP d8' `8b d8' 88 ,8P' o88 88 8D 88 8D\n"
|
||||||
|
"8P 88ooo88 88 88V8o 88 8P d8' `8bd8' 88,8P 88 `VoooY' `VoooY'\n"
|
||||||
|
"8b 88~~~88 88 88 V8o88 8b d8' 88 88`8b 88 .d~~~b. .d~~~b.\n"
|
||||||
|
"Y8b d8 88 88 .88. 88 V888 Y8b d8 d8' db 88 88 `88. 88 88 8D 88 8D\n"
|
||||||
|
" `Y88P' YP YP Y888888P VP V8P `Y88P' d88888P YP YP YD VP `Y888P' `Y888P'\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
std::cout << "Witaj w Chinczyku!\nAutor: B.Z. (2 EF-DI, L01, 177188)\n";
|
||||||
|
std::cout << "Kod zrodlowy: https://gitea.7o7.cx/sherl/Chinczyk188 na licencji GPLv3\n";
|
||||||
|
std::cout << "Instrukcja gry powinna zostac dolaczona do tej kopii gry, w przeciwnym razie\n"
|
||||||
|
"jest ona dostepna w repozytorium git.\n\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::readLeaderboards(std::string leaderboardLocation) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Spróbuj wczytać plik z zapisanymi wynikami
|
||||||
|
ss::parser<ss::throw_on_error> p{leaderboardLocation, " "};
|
||||||
|
|
||||||
|
for (const auto& [csvName, csvWins]: p.iterate<std::string, unsigned int>()) {
|
||||||
|
this->leaderboardName.push_back(csvName);
|
||||||
|
this->leaderboardWins.push_back(csvWins);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (ss::exception& e) {
|
||||||
|
|
||||||
|
// Jeżeli nie udało się wczytać pliku, spróbuj wczytać kopię zapasową
|
||||||
|
if (std::filesystem::exists("." + leaderboardLocation + ".old")) {
|
||||||
|
|
||||||
|
ss::parser<ss::throw_on_error> p{"." + leaderboardLocation + ".old", " "};
|
||||||
|
|
||||||
|
for (const auto& [csvName, csvWins]: p.iterate<std::string, unsigned int>()) {
|
||||||
|
this->leaderboardName.push_back(csvName);
|
||||||
|
this->leaderboardWins.push_back(csvWins);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Przekopiuj po cichu (verbose=false) dane do pliku głównego
|
||||||
|
this->dumpLeaderboards(leaderboardLocation, false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "Wystapil blad przy probie wczytania listy wynikow. \n"
|
||||||
|
"Gra sprobuje naprawic blad poprzez utworzenie nowego pliku z lista wynikow.\n"
|
||||||
|
"Nacisnij CTRL+C w przeciagu 10 sekund aby anulowac i wyjsc z programu.\n";
|
||||||
|
sf::sleep(sf::seconds(15));
|
||||||
|
|
||||||
|
// Utwórz plik
|
||||||
|
std::ofstream leaderboardFile;
|
||||||
|
leaderboardFile.open(leaderboardLocation);
|
||||||
|
leaderboardFile << "\n";
|
||||||
|
leaderboardFile.close();
|
||||||
|
|
||||||
|
// Przykładowe dane
|
||||||
|
this->leaderboardName.push_back("Anonymous");
|
||||||
|
this->leaderboardWins.push_back(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::dumpLeaderboards(std::string leaderboardLocation, bool verbose) const {
|
||||||
|
|
||||||
|
// Otwórz strumień wyjściowy do ścieżki leaderboardLocation
|
||||||
|
std::ofstream leaderboardFile;
|
||||||
|
leaderboardFile.open(leaderboardLocation);
|
||||||
|
for (int i = 0; i < (this->leaderboardName.size() & this->leaderboardWins.size()); i++) {
|
||||||
|
// Zapisz dane z wektora w formacie csv, spacja to separator
|
||||||
|
leaderboardFile << this->leaderboardName[i] << " " << this->leaderboardWins[i] << "\n";
|
||||||
|
}
|
||||||
|
leaderboardFile.close();
|
||||||
|
|
||||||
|
// Zmienna verbose decyduje o tym, czy chcemy wyświetlić komunikat o zapisie
|
||||||
|
if (verbose) std::cout << "Zapisano dane do pliku " << leaderboardLocation << ".\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Game::updateLeaderboards(std::string winnerNickname) {
|
||||||
|
|
||||||
|
bool updated = false;
|
||||||
|
unsigned int totalWins = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < (this->leaderboardName.size() & this->leaderboardWins.size()); i++) {
|
||||||
|
|
||||||
|
// Szukaj nick we wczytanych danych z pliku CSV
|
||||||
|
if (this->leaderboardName[i] == winnerNickname) {
|
||||||
|
|
||||||
|
totalWins = ++this->leaderboardWins[i];
|
||||||
|
updated = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updated) {
|
||||||
|
// Jeżeli to pierwsza wygrana tego gracza, to dodaj go do wektora
|
||||||
|
this->leaderboardName.push_back(winnerNickname);
|
||||||
|
this->leaderboardWins.push_back(1);
|
||||||
|
totalWins = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zapisz po cichu zmiany do obu plików CSV
|
||||||
|
this->dumpLeaderboards(LEADERBOARD_FILE, false);
|
||||||
|
this->dumpLeaderboards(std::string(".") + LEADERBOARD_FILE + std::string(".old"), false);
|
||||||
|
|
||||||
|
return totalWins;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::printLeaderboards() const {
|
||||||
|
|
||||||
|
// Zamienia dwa wektory w parę wektorów
|
||||||
|
// https://stackoverflow.com/a/18479184
|
||||||
|
std::vector<std::pair<std::string, int>> vectorPair(this->leaderboardName.size());
|
||||||
|
for (unsigned int i = 0; i < vectorPair.size(); i++) {
|
||||||
|
vectorPair[i] = std::make_pair(this->leaderboardName[i], this->leaderboardWins[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sortuje malejąco parę wektorów biorąc pod uwagę wartości w tym drugim
|
||||||
|
// https://stackoverflow.com/a/279878
|
||||||
|
std::sort(vectorPair.begin(), vectorPair.end(), [](auto &left, auto &right) {
|
||||||
|
return left.second > right.second;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const auto& [name, wins]: vectorPair) {
|
||||||
|
std::cout << "- " << name << ", " << wins << " wygranych\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::playStartTune() {
|
||||||
|
|
||||||
|
// Jeżli plik welcome_alt.ogg istnieje, załaduj go, a potem odtwórz.
|
||||||
|
if (!this->soundBuffer1.openFromFile("res/audio/welcome_alt.ogg"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Aby dało się usłyszeć dźwięk, nie może on wyjść poza zakres (out of scope).
|
||||||
|
// Z tego powodu zapisujemy odnośnik do bufora w pamięci programu (w klasie Game).
|
||||||
|
this->soundBuffer1.play();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Game::initVariables() {
|
void Game::initVariables() {
|
||||||
|
|
||||||
|
// Ustaw wartości na domyślne.
|
||||||
this->window = nullptr;
|
this->window = nullptr;
|
||||||
|
this->leaderboardLocation = LEADERBOARD_FILE;
|
||||||
|
|
||||||
|
// Wczytaj tło - bitmapę planszy.
|
||||||
|
// loadFromFile() zwraca True w przypadku pomyślnego
|
||||||
|
// wczytania tekstury.
|
||||||
|
if (!this->boardTexture.loadFromFile("res/sprites/board.png")) {
|
||||||
|
|
||||||
|
// Jeśli nie uda nam się wczytać tekstury:
|
||||||
|
std::cerr << "Uwaga: Nie udalo sie wczytac "
|
||||||
|
"wymaganej tekstury planszy z \"res/sprites/board.png\"!\n"
|
||||||
|
"Upewnij sie, ze plik .exe jest we wlasciwym katalogu, "
|
||||||
|
"a gra zostala w pelni wypakowana wraz z folderem \"res\".\n";
|
||||||
|
|
||||||
|
sf::sleep(sf::seconds(10));
|
||||||
|
this->window->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spróbuj wczytać listę wyników z pliku
|
||||||
|
this->readLeaderboards(leaderboardLocation);
|
||||||
|
// Zapisz po cichu (stąd false) kopię zapasową listy wyników
|
||||||
|
this->dumpLeaderboards("." + leaderboardLocation + ".old", false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::initWindow() {
|
void Game::initWindow() {
|
||||||
|
|
||||||
this->videoMode = sf::VideoMode::getDesktopMode();
|
// Dwuwymiarowy, wektor typu (u)nsigned int.
|
||||||
this->videoMode.width /= 2;
|
sf::Vector2u textureSize = this->boardTexture.getSize();
|
||||||
this->videoMode.height /= 2;
|
|
||||||
|
|
||||||
this->window = new sf::RenderWindow(this->videoMode, "Chinczyk188", sf::Style::Default);
|
// Aby okno zmieściło się na większości wyświetlaczy,
|
||||||
|
// sprawmy, aby zajmowało ono około 450x450 pikseli,
|
||||||
|
// czyli dokładnie połowę z rozdzielczości tekstury planszy.
|
||||||
|
this->videoMode.width = textureSize.x / 2;
|
||||||
|
this->videoMode.height = textureSize.y / 2;
|
||||||
|
|
||||||
|
// Stwórz okno.
|
||||||
|
this->window = new sf::RenderWindow(
|
||||||
|
this->videoMode,
|
||||||
|
"Okno planszy - Chinczyk188",
|
||||||
|
sf::Style::Default);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::initBoard() {
|
||||||
|
|
||||||
|
// Wczytaj wymaganą teksturę planszy
|
||||||
|
this->boardSprite.setTexture(this->boardTexture);
|
||||||
|
|
||||||
|
// Ustaw pozycję grafiki.
|
||||||
|
this->boardSprite.setPosition(0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::initView() {
|
||||||
|
|
||||||
|
// Ze względu na to, że długość krawędzi okna jest dwa razy mniejsza
|
||||||
|
// od tekstury planszy, powinniśmy to zrównoważyć powiększając
|
||||||
|
// widok o tą samą wartość.
|
||||||
|
sf::Vector2f viewSize(
|
||||||
|
static_cast<float>(2 * this->videoMode.width),
|
||||||
|
static_cast<float>(2 * this->videoMode.height)
|
||||||
|
);
|
||||||
|
|
||||||
|
this->view.setSize(viewSize);
|
||||||
|
this->view.setCenter(viewSize.x / 2.0f, viewSize.y / 2.0f);
|
||||||
|
|
||||||
|
// Ustawiamy widok na wyznaczone wartości.
|
||||||
|
this->window->setView(this->view);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::handleResize(unsigned int newWidth, unsigned int newHeight) {
|
||||||
|
|
||||||
|
// Aby zapobiec sytuacji, w której po zmianie rozmiaru
|
||||||
|
// okno byłoby większe od rozdzielczości ekranu,
|
||||||
|
// niech krawędź okna wynosi minimum z nowej szerokości i wysokości,
|
||||||
|
// zachowując przy tym proporcję 1:1 planszy.
|
||||||
|
unsigned int newSize = std::min(newWidth, newHeight);
|
||||||
|
this->window->setSize(sf::Vector2u(newSize, newSize));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::Game() {
|
Game::Game() {
|
||||||
|
//:
|
||||||
|
// thread(std::thread([this]() {
|
||||||
|
// while (this->running()) {
|
||||||
|
// this->update();
|
||||||
|
// this->render();
|
||||||
|
// sf::sleep(sf::milliseconds(100));
|
||||||
|
// } })) {
|
||||||
|
|
||||||
this->initVariables();
|
// Konstruktor klasy. Klasę Game tworzymy poprzez
|
||||||
this->initWindow();
|
// ustawienie domyślnych wartości i stworzenie okna.
|
||||||
|
|
||||||
|
this->board.initVariables();
|
||||||
|
this->board.initWindow();
|
||||||
|
this->board.initBoard();
|
||||||
|
this->board.initView(); // widok musi być zainicjalizowany po oknie
|
||||||
|
|
||||||
|
// Puść melodyjkę
|
||||||
|
this->playStartTune();
|
||||||
|
|
||||||
|
// Wyświetl witający tekst
|
||||||
|
this->printGameWelcomeText();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::~Game() {
|
Game::~Game() {
|
||||||
|
|
||||||
delete this->window;
|
// W destruktorze zapisujemy dane i usuwamy okno.
|
||||||
|
this->dumpLeaderboards();
|
||||||
|
delete this->window; // alternatywnie: this->window->close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool Game::running() const {
|
const bool Game::running() const {
|
||||||
|
|
||||||
return this->window->isOpen();
|
// Akcesor dla isOpen()
|
||||||
|
//return this->window->isOpen();
|
||||||
|
return this->board.running();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::pollEvents() {
|
void Game::pollEvents() {
|
||||||
|
|
||||||
while (this->window->pollEvent(this->ev)) {
|
while (this->window->pollEvent(this->ev)) {
|
||||||
|
|
||||||
switch (this->ev.type) {
|
switch (this->ev.type) {
|
||||||
|
|
||||||
case sf::Event::Closed:
|
case sf::Event::Closed:
|
||||||
this->window->close();
|
this->window->close();
|
||||||
break;
|
break;
|
||||||
case sf::Event::KeyPressed:
|
|
||||||
if (this->ev.key.code == sf::Keyboard::Escape) this->window->close();
|
case sf::Event::Resized:
|
||||||
|
this->handleResize(this->ev.size.width, this->ev.size.height);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case sf::Event::KeyPressed:
|
||||||
|
if (this->ev.key.code == sf::Keyboard::Escape)
|
||||||
|
this->window->close();
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::update() {
|
void Game::update() {
|
||||||
|
|
||||||
|
// Obecnie wrapper dla metody
|
||||||
|
// pollEvents(), nasłuchiwanie wydarzeń.
|
||||||
this->pollEvents();
|
this->pollEvents();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::render() {
|
void Game::render() {
|
||||||
|
|
||||||
// EN: Render logic
|
// Mechanizm renderowania
|
||||||
// PL: Mechanizm renderowania
|
|
||||||
this->window->clear(sf::Color(255, 0, 0, 255));
|
// Czyszczenie ekranu
|
||||||
|
this->window->clear(sf::Color::White);
|
||||||
|
// Rysowanie tła
|
||||||
|
this->window->draw(this->boardSprite);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// PL: Mechanizm wyświetlania
|
// Mechanizm wyświetlania
|
||||||
// W celu wyświetlenia na ekranie wyniku renderowania
|
// W celu wyświetlenia na ekranie wyniku renderowania
|
||||||
this->window->display();
|
this->window->display();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::run() {
|
||||||
|
|
||||||
|
Engine engine;
|
||||||
|
board.updateAndRender();
|
||||||
|
|
||||||
|
// this->update();
|
||||||
|
// this->render();
|
||||||
|
|
||||||
|
int numPlayers = 2;
|
||||||
|
std::cout << "Podaj prosze liczbe graczy (2-4):\n> ";
|
||||||
|
std::cin >> numPlayers;
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
if (numPlayers < 2) numPlayers = 2;
|
||||||
|
if (numPlayers > 4) numPlayers = 4;
|
||||||
|
|
||||||
|
const char* colorNames[] = {"czerwony", "niebieski", "zolty", "zielony"};
|
||||||
|
// Uzyskaj dane o użytkownikach
|
||||||
|
for (int i = 0; i < numPlayers; i++) {
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string str_seed = std::to_string(std::time(nullptr)); // czas
|
||||||
|
|
||||||
|
std::cout << "Wpisz nazwe gracza " << (i + 1) << " (" << colorNames[i] << "): ";
|
||||||
|
std::cin >> name;
|
||||||
|
|
||||||
|
#ifndef CHINCZYK188_IGNORE_USER_SEED
|
||||||
|
// Jeżeli nie została zdefiniowana flaga do ignorowania ziarna użytkownika
|
||||||
|
// (deterministyczne losowanie), to pozwól na wprowadzanie ziaren.
|
||||||
|
std::cout << "Wpisz ziarno gracza " << (i + 1) << " (" << colorNames[i] << "): ";
|
||||||
|
std::cin >> str_seed;
|
||||||
|
#endif
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
short color = static_cast<short>(i);
|
||||||
|
unsigned int seed = std::hash<std::string_view>{}(str_seed);
|
||||||
|
engine.addPlayer(name, seed, color);
|
||||||
|
|
||||||
|
board.updateAndRender();
|
||||||
|
//this->update();
|
||||||
|
//this->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Przekaż ev i window, aby obsługiwać zdarzenia
|
||||||
|
// w Engine
|
||||||
|
engine.startGame(this->board);
|
||||||
|
|
||||||
|
// Główna pętla gry
|
||||||
|
while (board.running()) {
|
||||||
|
|
||||||
|
board.updateAndRender();
|
||||||
|
// this->update(); // do threadów
|
||||||
|
//this->render();
|
||||||
|
|
||||||
|
if (!engine.isGameOver()) {
|
||||||
|
engine.nextTurn();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// updateLeaderboard() inkrementuje i zwraca liczbę wygranych przekazanego gracza
|
||||||
|
std::cout << "To jego(/jej) "
|
||||||
|
<< updateLeaderboards(engine.winnerNickname) << ". wygrana!\n";
|
||||||
|
|
||||||
|
std::cout << "--------------------\n\n"
|
||||||
|
<< "Statystyki:\n";
|
||||||
|
this->printLeaderboards();
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
sf::sleep(sf::seconds(10.0f));
|
||||||
|
board.closeWindow();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,59 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#define LEADERBOARD_FILE "tablica_wynikow.csv"
|
||||||
|
#include "Board.hpp"
|
||||||
|
#include <thread>
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <SFML/Audio.hpp>
|
||||||
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// Wskaźnik na okno.
|
||||||
sf::RenderWindow* window;
|
sf::RenderWindow* window;
|
||||||
sf::VideoMode videoMode;
|
sf::VideoMode videoMode;
|
||||||
sf::Event ev;
|
|
||||||
|
|
||||||
|
sf::Texture boardTexture;
|
||||||
|
sf::Sprite boardSprite;
|
||||||
|
|
||||||
|
std::vector<std::string> leaderboardName;
|
||||||
|
std::vector<unsigned int> leaderboardWins;
|
||||||
|
sf::Music soundBuffer1;
|
||||||
|
Board board;
|
||||||
|
|
||||||
|
// Metody
|
||||||
void initVariables();
|
void initVariables();
|
||||||
void initWindow();
|
void initWindow();
|
||||||
|
void initBoard();
|
||||||
|
void initView();
|
||||||
|
void playStartTune();
|
||||||
|
void handleResize(unsigned int newWidth, unsigned int newHeight);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Aby przekazać je do Engine
|
||||||
|
sf::Event ev;
|
||||||
|
std::string leaderboardLocation;
|
||||||
|
sf::View view;
|
||||||
|
|
||||||
|
// Konstruktor, destruktor
|
||||||
Game();
|
Game();
|
||||||
virtual ~Game();
|
~Game();
|
||||||
|
|
||||||
|
// Akcesor
|
||||||
const bool running() const;
|
const bool running() const;
|
||||||
void pollEvents();
|
|
||||||
|
|
||||||
|
// Metody klasy
|
||||||
|
void pollEvents();
|
||||||
void update();
|
void update();
|
||||||
void render();
|
void render();
|
||||||
|
void printGameWelcomeText() const;
|
||||||
|
void readLeaderboards(std::string leaderboardLocation);
|
||||||
|
void dumpLeaderboards(std::string leaderboardLocation = LEADERBOARD_FILE, bool verbose = true) const;
|
||||||
|
unsigned int updateLeaderboards(std::string winnerNickname);
|
||||||
|
void printLeaderboards() const;
|
||||||
|
void run();
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -3,13 +3,14 @@
|
|||||||
# EN: Warning: mingw-w64-x86_64-gcc-14.1.0-3 is the last version of gcc, which supports wildcards ("*.cpp").
|
# EN: Warning: mingw-w64-x86_64-gcc-14.1.0-3 is the last version of gcc, which supports wildcards ("*.cpp").
|
||||||
# PL: Uwaga: mingw-w64-x86_64-gcc-14.1.0-3 to ostatnia wspierana wersja gcc, w której można stosować wildcard'y ("*.cpp").
|
# PL: Uwaga: mingw-w64-x86_64-gcc-14.1.0-3 to ostatnia wspierana wersja gcc, w której można stosować wildcard'y ("*.cpp").
|
||||||
CC = "C:\\msys64\\mingw64\\bin\\g++.exe"
|
CC = "C:\\msys64\\mingw64\\bin\\g++.exe"
|
||||||
DEPS = -lsfml-graphics-s -lsfml-window-s -lsfml-system-s -lopengl32 -lwinmm -lgdi32 -DSFML_STATIC
|
DEPS = -lsfml-graphics-s -lsfml-window-s -lsfml-audio-s -lopenal32 -lflac -lvorbisenc -lvorbisfile -lvorbis -logg -lsfml-system-s -lopengl32 -lwinmm -lgdi32 -lpthread
|
||||||
#LINK = -L.
|
LINK = -L. -Lres/SFML/lib-mingw/
|
||||||
|
FLAGS = -DSFML_STATIC # -DCHINCZYK188_IGNORE_USER_SEED
|
||||||
OUTPUT = output.exe
|
OUTPUT = output.exe
|
||||||
CPPSTD = c++17
|
CPPSTD = c++17
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$(CC) -g "*.cpp" $(DEPS) $(LINK) -std=$(CPPSTD) -static -static-libgcc -fno-keep-inline-dllexport -o $(OUTPUT)
|
$(CC) -g "*.cpp" $(LINK) $(DEPS) -std=$(CPPSTD) $(FLAGS) -static -static-libgcc -fno-keep-inline-dllexport -Os -s -Wl,--build-id=none -o $(OUTPUT)
|
||||||
|
|
||||||
run: default
|
run: default
|
||||||
$(OUTPUT)
|
$(OUTPUT)
|
||||||
|
|||||||
59
Chinczyk188/Pawn.cpp
Normal file
59
Chinczyk188/Pawn.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include "Pawn.hpp"
|
||||||
|
|
||||||
|
// Konstruktor
|
||||||
|
Pawn::Pawn() {
|
||||||
|
|
||||||
|
this->position = -1;
|
||||||
|
this->grid_x = -1;
|
||||||
|
this->grid_y = -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gettery i settery
|
||||||
|
int Pawn::getRelativePosition() const {
|
||||||
|
|
||||||
|
return this->position;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pawn::setRelativePosition(int position) {
|
||||||
|
|
||||||
|
this->position = position;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int Pawn::move(int fields) {
|
||||||
|
|
||||||
|
switch (fields) {
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
// Przenieś do bazy
|
||||||
|
// 0 = ok
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
// Wstaw na planszę
|
||||||
|
// 0 = ok
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Sprawdź:
|
||||||
|
// a) czy da się wejść na to miejsce
|
||||||
|
// b) czy są pionki do zbicia
|
||||||
|
// c) czy są inne pionki tego samego gracza
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Pawn::isAtBase() const {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pawn::sendToBase() {
|
||||||
|
|
||||||
|
}
|
||||||
22
Chinczyk188/Pawn.hpp
Normal file
22
Chinczyk188/Pawn.hpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Pawn {
|
||||||
|
public:
|
||||||
|
Pawn();
|
||||||
|
|
||||||
|
// Gettery i settery
|
||||||
|
int getRelativePosition() const;
|
||||||
|
void setRelativePosition(int position);
|
||||||
|
|
||||||
|
bool isAtBase() const;
|
||||||
|
bool isActive() const;
|
||||||
|
bool isAtHome() const;
|
||||||
|
void sendToBase();
|
||||||
|
|
||||||
|
int move(int fields);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int position; // -1 oznacza pionek w bazie
|
||||||
|
int grid_x;
|
||||||
|
int grid_y;
|
||||||
|
};
|
||||||
62
Chinczyk188/Player.cpp
Normal file
62
Chinczyk188/Player.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#include "Player.hpp"
|
||||||
|
|
||||||
|
Player::Player(const std::string& name, unsigned int seed, short color):
|
||||||
|
name(name), seed(seed), color(color), pawnsFinished(0) {}
|
||||||
|
|
||||||
|
const std::string& Player::getName() const {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Player::getSeed() const {
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::initializePawns(int totalPawns) {
|
||||||
|
pawns.resize(totalPawns);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Player::getRollCount() const {
|
||||||
|
return this->rollCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::incrementRollCount() {
|
||||||
|
this->rollCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
short Player::getColor() const {
|
||||||
|
return this->color;
|
||||||
|
}
|
||||||
|
|
||||||
|
short Player::tryMovingPawn(short pawnID, short fields) {
|
||||||
|
// this->pawnsFinished = 4; // do testowania, wymuszania zakończenia gry
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::movePawn(int pawnIndex, int steps) {
|
||||||
|
if (pawnIndex < 0 || pawnIndex >= pawns.size()) return;
|
||||||
|
|
||||||
|
// TODO: zaimplementować logikę ruchu pionków
|
||||||
|
Pawn& pawn = pawns[pawnIndex];
|
||||||
|
if (pawn.isAtBase()) {
|
||||||
|
if (steps == 6) {
|
||||||
|
pawn.setRelativePosition(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int newPosition = pawn.getRelativePosition() + steps;
|
||||||
|
// TODO: sprawdź pozycję pionków
|
||||||
|
pawn.setRelativePosition(newPosition);
|
||||||
|
|
||||||
|
if (newPosition >= 51/* "koniec", do przerobienia */) {
|
||||||
|
pawn.setRelativePosition(51/* "koniec" */);
|
||||||
|
pawnsFinished++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Pawn>& Player::getPawns() {
|
||||||
|
return pawns;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::hasWon() const {
|
||||||
|
return pawnsFinished == pawns.size();
|
||||||
|
}
|
||||||
38
Chinczyk188/Player.hpp
Normal file
38
Chinczyk188/Player.hpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "Pawn.hpp"
|
||||||
|
|
||||||
|
class Player {
|
||||||
|
public:
|
||||||
|
Player(const std::string& name, unsigned int seed, short color);
|
||||||
|
|
||||||
|
// Akcesory
|
||||||
|
const std::string& getName() const;
|
||||||
|
unsigned int getSeed() const;
|
||||||
|
int getRollCount() const;
|
||||||
|
short getColor() const;
|
||||||
|
|
||||||
|
void incrementRollCount();
|
||||||
|
|
||||||
|
// Zarządzanie pionkami
|
||||||
|
void initializePawns(int totalPawns);
|
||||||
|
void movePawn(int pawnIndex, int steps);
|
||||||
|
short tryMovingPawn(short pawnID, short fields);
|
||||||
|
std::vector<Pawn>& getPawns();
|
||||||
|
short pawnsAtBase = 4;
|
||||||
|
short pawnsActive = 0;
|
||||||
|
short pawnsAtHome = 0;
|
||||||
|
|
||||||
|
bool hasWon() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
unsigned int seed;
|
||||||
|
std::vector<Pawn> pawns;
|
||||||
|
short color;
|
||||||
|
|
||||||
|
int rollCount = 0;
|
||||||
|
|
||||||
|
int pawnsFinished; // to nie to samo, co pawnsAtHome
|
||||||
|
};
|
||||||
@@ -4,11 +4,9 @@ int main() {
|
|||||||
|
|
||||||
Game game;
|
Game game;
|
||||||
|
|
||||||
while(game.running()) {
|
while (game.running()) {
|
||||||
|
|
||||||
game.update();
|
game.run();
|
||||||
|
|
||||||
game.render();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
Chinczyk188/res/audio/PeteBarry_pawnmove.ogg
Normal file
BIN
Chinczyk188/res/audio/PeteBarry_pawnmove.ogg
Normal file
Binary file not shown.
BIN
Chinczyk188/res/audio/wardoctor17_diceroll.ogg
Normal file
BIN
Chinczyk188/res/audio/wardoctor17_diceroll.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
Chinczyk188/res/audio/welcome_alt.ogg
Normal file
BIN
Chinczyk188/res/audio/welcome_alt.ogg
Normal file
Binary file not shown.
BIN
Chinczyk188/res/sprites/board_placesOverlay.png
Normal file
BIN
Chinczyk188/res/sprites/board_placesOverlay.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
Reference in New Issue
Block a user