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.
|
||||
# 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.
|
||||
# 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>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>SFML_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;SFML_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)res\SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<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>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -119,21 +121,36 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>SFML_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;SFML_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)res\SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<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>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Board.cpp" />
|
||||
<ClCompile Include="Engine.cpp" />
|
||||
<ClCompile Include="Game.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>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -18,5 +18,40 @@
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</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>
|
||||
</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 <SFML/System/Sleep.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#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() {
|
||||
|
||||
// Ustaw wartości na domyślne.
|
||||
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() {
|
||||
|
||||
this->videoMode = sf::VideoMode::getDesktopMode();
|
||||
this->videoMode.width /= 2;
|
||||
this->videoMode.height /= 2;
|
||||
// Dwuwymiarowy, wektor typu (u)nsigned int.
|
||||
sf::Vector2u textureSize = this->boardTexture.getSize();
|
||||
|
||||
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() {
|
||||
//:
|
||||
// thread(std::thread([this]() {
|
||||
// while (this->running()) {
|
||||
// this->update();
|
||||
// this->render();
|
||||
// sf::sleep(sf::milliseconds(100));
|
||||
// } })) {
|
||||
|
||||
this->initVariables();
|
||||
this->initWindow();
|
||||
// Konstruktor klasy. Klasę Game tworzymy poprzez
|
||||
// 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() {
|
||||
|
||||
delete this->window;
|
||||
// W destruktorze zapisujemy dane i usuwamy okno.
|
||||
this->dumpLeaderboards();
|
||||
delete this->window; // alternatywnie: this->window->close();
|
||||
|
||||
}
|
||||
|
||||
const bool Game::running() const {
|
||||
|
||||
return this->window->isOpen();
|
||||
// Akcesor dla isOpen()
|
||||
//return this->window->isOpen();
|
||||
return this->board.running();
|
||||
|
||||
}
|
||||
|
||||
void Game::pollEvents() {
|
||||
|
||||
while (this->window->pollEvent(this->ev)) {
|
||||
|
||||
switch (this->ev.type) {
|
||||
|
||||
case sf::Event::Closed:
|
||||
this->window->close();
|
||||
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;
|
||||
|
||||
case sf::Event::KeyPressed:
|
||||
if (this->ev.key.code == sf::Keyboard::Escape)
|
||||
this->window->close();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Game::update() {
|
||||
|
||||
// Obecnie wrapper dla metody
|
||||
// pollEvents(), nasłuchiwanie wydarzeń.
|
||||
this->pollEvents();
|
||||
|
||||
}
|
||||
|
||||
void Game::render() {
|
||||
|
||||
// EN: Render logic
|
||||
// PL: Mechanizm renderowania
|
||||
this->window->clear(sf::Color(255, 0, 0, 255));
|
||||
// Mechanizm renderowania
|
||||
|
||||
// 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
|
||||
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
|
||||
#define LEADERBOARD_FILE "tablica_wynikow.csv"
|
||||
#include "Board.hpp"
|
||||
#include <thread>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <SFML/System/Sleep.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
class Game {
|
||||
|
||||
private:
|
||||
|
||||
// Wskaźnik na okno.
|
||||
sf::RenderWindow* window;
|
||||
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 initWindow();
|
||||
void initBoard();
|
||||
void initView();
|
||||
void playStartTune();
|
||||
void handleResize(unsigned int newWidth, unsigned int newHeight);
|
||||
|
||||
public:
|
||||
|
||||
// Aby przekazać je do Engine
|
||||
sf::Event ev;
|
||||
std::string leaderboardLocation;
|
||||
sf::View view;
|
||||
|
||||
// Konstruktor, destruktor
|
||||
Game();
|
||||
virtual ~Game();
|
||||
~Game();
|
||||
|
||||
// Akcesor
|
||||
const bool running() const;
|
||||
void pollEvents();
|
||||
|
||||
// Metody klasy
|
||||
void pollEvents();
|
||||
void update();
|
||||
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").
|
||||
# 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"
|
||||
DEPS = -lsfml-graphics-s -lsfml-window-s -lsfml-system-s -lopengl32 -lwinmm -lgdi32 -DSFML_STATIC
|
||||
#LINK = -L.
|
||||
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. -Lres/SFML/lib-mingw/
|
||||
FLAGS = -DSFML_STATIC # -DCHINCZYK188_IGNORE_USER_SEED
|
||||
OUTPUT = output.exe
|
||||
CPPSTD = c++17
|
||||
|
||||
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
|
||||
$(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;
|
||||
|
||||
while(game.running()) {
|
||||
while (game.running()) {
|
||||
|
||||
game.update();
|
||||
|
||||
game.render();
|
||||
game.run();
|
||||
|
||||
}
|
||||
|
||||
|
||||
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