Page MenuHomePhabricator (Chris)

No OneTemporary

Size
45 KB
Referenced Files
None
Subscribers
None
diff --git a/assets/img/board_diamonds.png b/assets/img/board_diamonds.png
index df52bc5..1003177 100644
Binary files a/assets/img/board_diamonds.png and b/assets/img/board_diamonds.png differ
diff --git a/boarddiamond.cpp b/boarddiamond.cpp
index 96e570b..cbe2602 100644
--- a/boarddiamond.cpp
+++ b/boarddiamond.cpp
@@ -1,27 +1,33 @@
#include "boarddiamond.h"
BoardDiamond::BoardDiamond()
{
}
BoardDiamond::BoardDiamond(TextureHolder *textures, int idNumber,
int element, int boardPosition)
{
this->textures = textures;
this->element = element;
this->boardPosition = boardPosition;
spriteHolder.setTexture(this->textures->textureBoardDiamond);
- sf::IntRect textureRect(idNumber*44, 44, (idNumber*44)+idNumber,44);
+ sf::IntRect textureRect(idNumber*44, 0, 44,44);
spriteHolder.setTextureRect(textureRect);
+ setBoardPosition(boardPosition);
}
void BoardDiamond::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
- states.transform *= getTransform();
-// target.draw(animatedSprite, states);
+ if (boardPosition>-1)
+ {
+ states.transform *= getTransform();
+ sf::Vector2f where(getPosition());
+ std::cout << "drawing " << where.x << " " << where.y << std::endl;
+ target.draw(spriteHolder, states);
+ }
}
void BoardDiamond::update(sf::Time deltaTime, std::set<int> &busyTiles)
{
}
diff --git a/boarddiamondseq.cpp b/boarddiamondseq.cpp
index 08d9668..1a03ce0 100644
--- a/boarddiamondseq.cpp
+++ b/boarddiamondseq.cpp
@@ -1,29 +1,53 @@
#include "boarddiamondseq.h"
BoardDiamondSeq::BoardDiamondSeq(TextureHolder *textures)
{
this->textures = textures;
-
- diamonds[0] = BoardDiamond(textures, 0,0, 5);
- diamonds[1] = BoardDiamond(textures, 0,0, 6);
- diamonds[2] = BoardDiamond(textures, 1,0, 7);
- diamonds[3] = BoardDiamond(textures, 1,0, 17);
-
+ for (int i=0; i<efc::diamondsNumber; i++)
+ {
+ diamonds[i] = BoardDiamond(this->textures,
+ efc::DIAMONDS_SETUP[i][0],
+ efc::DIAMONDS_SETUP[i][1],
+ efc::DIAMONDS_SETUP[i][2]);
+ }
+ reorder();
}
void BoardDiamondSeq::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.transform *= getTransform();
- for (int i=1; i<DIAMONDS_NUMBER; i++)
+ for (int i=0; i<efc::diamondsNumber; i++)
{
-
target.draw(diamonds[i],states);
}
}
-void BoardDiamondSeq::update(sf::Time deltaTime, std::set<int> &busyTiles)
+std::array<int,efc::diamondsNumber> BoardDiamondSeq::getBoardPositions()
{
+ std::array<int, efc::diamondsNumber> results;
+ for (int i=0; i<efc::diamondsNumber; i++)
+ {
+ results[i] = diamonds[i].getBoardPosition();
+ }
+ return results;
+}
+
+void BoardDiamondSeq::reorder()
+{
+ srand((unsigned)time(0));
+
+ for (int element=0;element<4;element++)
+ {std::cout << "UP reorder " << ""<< efc::diamondsNumber/4 << "" << element << std::endl;
+ int start = element;
+ for (int i=start*14;i<(efc::diamondsNumber/4)+(start*14);i++)
+ {
+ std::cout << "reorder " << i << std::endl;
+ int step = rand()%efc::numberSteps;
+ diamonds[i].setBoardPosition(efc::occupiedFields[start][step]);
+ }
+ }
}
+ ;
diff --git a/boarddiamondseq.h b/boarddiamondseq.h
index f48e6b7..704a973 100644
--- a/boarddiamondseq.h
+++ b/boarddiamondseq.h
@@ -1,37 +1,38 @@
#ifndef BOARDDIAMONDSEQ_H
#define BOARDDIAMONDSEQ_H
-
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
#include <set>
#include "textureholder.h"
#include <SFML/Graphics.hpp>
#include "boarddiamond.h"
/*!
* \brief The BoardDiamondSeq class
* We are going to have 2 cards / diamonds of each element per each area,
* which gives 2*4*4 = 32 cards diamonds of elements on the board.
*
* Additionally there will be extra 6 white diamonds per area to collect, which
* gives 4*6 = 24 diamonds on the board.
*
- * Together it would give 32 + 24 = 60 diamonds cards/diamonds together,
+ * Together it would give 32 + 24 = 56 diamonds cards/diamonds together,
* 15 per area.
*/
class BoardDiamondSeq : public sf::Drawable, public sf::Transformable
{
public:
BoardDiamondSeq(TextureHolder *textures);
- virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
- void update(sf::Time deltaTime, std::set<int>& busyTiles);
TextureHolder *textures;
+ BoardDiamond diamonds[efc::diamondsNumber];
- const static int DIAMONDS_NUMBER = 4;
- BoardDiamond diamonds[DIAMONDS_NUMBER];
-};
-
+ std::array<int,efc::diamondsNumber> getBoardPositions();
+ virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
+ void reorder();
+};
#endif // BOARDDIAMONDSEQ_H
diff --git a/data.cpp b/data.cpp
index f37e090..1422354 100644
--- a/data.cpp
+++ b/data.cpp
@@ -1,98 +1,138 @@
#include <data.h>
namespace efc {
std::string seasonsNames[4] = {"spring", "summer", "fall", "winter"};
// This array defines fields occupied by the river
int terrainArray[24] = {
8, 24, 40, 56, 72, 88,
113, 114, 115, 116, 117, 118,
138, 139, 140, 141, 142, 143,
167, 183, 199, 215, 231, 247
};
/*
* 0
* 16
* 32
* 48
* 64
* 80
* 96
* 112
* 128
* 144
* 160
* 176
* 192
*/
int possibleExits[4] = {119,120,135,136};
std::array<std::array<int,2>,256> boards = {
{
{-1,1}, {0,2}, {1,3}, {2,4}, {3,5}, {4,21}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {11,26}, {12,10}, {13,11}, {14,12}, {15,13}, {-1,14},
{-1,-1}, {18,33}, {19,17}, {20,18}, {21,19}, {5,20}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {10, 27,}, {26,28}, {27,29}, {28,30}, {29,46}, {-1,-1},
{33,48}, {17,32}, {-1,-1}, {51,36}, {35,37}, {36,38}, {37,54}, {-1,-1}, {-1,-1}, {-1,-1}, {43,58}, {44,42}, {60,43}, {-1,-1}, {30,47}, {46,63},
{32,49}, {48,50}, {49,51}, {50,35}, {-1,-1}, {54,69}, {38,53}, {-1,-1}, {-1,-1}, {58,73}, {42,57}, {-1,-1}, {61,44}, {62,60}, {63,61}, {47,62},
{65,80}, {66,64}, {67,65}, {68,66}, {69,67}, {53,68}, {-1,-1}, {-1,-1}, {-1,-1}, {57,74}, {73,75}, {74,76}, {75,77}, {76,78}, {77,79}, {78,95},
{64,81}, {80,97}, {-1,-1}, {99,84}, {83,85}, {84,101}, {-1,-1}, {-1,-1}, {-1,-1}, {90,105}, {91,89}, {92,90}, {108,91}, {-1,-1}, {95,110}, {79,94},
{-1,-1}, {81,98}, {97,99}, {98,83}, {-1,-1}, {85,102}, {101,118}, {-1,-1}, {105,120}, {89,104}, {-1,-1}, {-1,-1}, {109,92}, {110,108}, {94,109}, {-1,-1},
{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {102, 119},{118,-1}, {104,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1},
{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} , {151,-1}, {137,-1}, {153,136}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1},
{-1,-1}, {161,146}, {145,147}, {146,163}, {-1,-1}, {-1,-1}, {166,151}, {150,135} ,{-1,-1}, {154,137}, {170,153}, {-1,-1}, {157,172}, {158,156}, {174,157}, {-1,-1},
{176,161},{160,145}, {-1,-1}, {147,164}, {163,165}, {164,166}, {165,150}, {-1,-1}, {-1,-1}, {-1,-1}, {171,154}, {172,170}, {156,171}, {-1,-1}, {175,158}, {191,174},
{177,160},{178,176}, {179,177}, {180,178}, {181,179}, {182,180}, {198,181}, {-1,-1}, {-1,-1}, {-1,-1}, {202,187}, {186,188}, {187,189}, {188,190}, {189,191}, {190,175},
{208,193},{192,194}, {193,195}, {194,211}, {-1,-1}, {213,198}, {197,182}, {-1,-1}, {-1,-1}, {217,202}, {201,186}, {-1,-1}, {205,220}, {206,204}, {207,205}, {223,206},
{209,192},{225,208}, {-1,-1}, {195,212}, {211,213}, {212,197}, {-1,-1}, {-1,-1}, {-1,-1}, {218,201}, {219,217}, {220,218}, {204,219}, {-1,-1}, {238,223}, {222,207},
{-1,-1}, {226,209}, {227,225}, {228,226}, {229,227}, {245,228}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {250,235}, {234,236}, {235,237}, {236,238}, {237,222}, {-1,-1},
{-1,241}, {240,242},{241,243}, {242,244}, {243,245}, {244,229}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {251,234}, {252,250}, {253,251}, {254,252}, {255,253}, {-1,254},
},
};
+std::array<std::array<int,numberSteps>,4> occupiedFields =
+{
+ {
+ {1,2,3,4,5,17,18,19,20,21,32,33,35,36,37,38,48,49,50,51,53,54,64,65,66,67,68,69,80,81,83,84,85,97,98,99,101,102,118},
+ {10,11,12,13,14,26,27,28,29,30,42,43,44,46,47,57,58,60,61,62,63,73,74,75,76,77,78,79,89,90,91,92,94,95,104,105,108,109,110},
+ {145,146,147,150,151,160,161,163,164,165,166,176,177,178,179,180,181,182,192,193,194,195,197,198,208,209,211,212,213,225,226,227,228,229,241,242,243,244,245},
+ {137,153,154,156,157,158,170,171,172,174,175,186,187,188,189,190,191,201,202,204,205,206,207,217,218,219,220,222,223,234,235,236,237,238,250,251,252,253,254}
+ }
+};
//{8,813}, {24, 803}, {40, 803}, {56, 803}, {72, 803} ,{88, 801},
//{167,809}, {183, 803}, {199, 803}, {215, 803}, {231, 803} ,{247, 8},
//{8,813}, {24, 803}, {40, 803}, {56, 803}, {72, 803} ,{88, 801},
//{8,813}, {24, 803}, {40, 803}, {56, 803}, {72, 803} ,{88, 801},
//level[8] = 813;
//level[24] = 803;
//level[40] = 803;
//level[56] = 803;
//level[72] = 803;
//level[88] = 801;
//level[167] = 809;
//level[183] = 803;
//level[199] = 803;
//level[215] = 803;
//level[231] = 803;
//level[247] = 812;
//level[112] = 811;
//for (int i=113;i<117;i++)
// level[i] = 816;
//level[117] = 815;
//level[138] = 800;
//for (int i=139;i<143;i++)
// level[i] = 816;
//level[143] = 814;
// Colors for the board elements
//sf::Color playersColors[4] = {
// sf::Color(0, 150,255,255),
// sf::Color(50, 230,50,255),
// sf::Color(230, 50,50,255),
// sf::Color(150, 150,150,255)
//};
sf::Color playersColors[4] = {
sf::Color(122, 185,246,255),
sf::Color(144, 226,106,255),
sf::Color(255, 163,142,255),
sf::Color(250, 255,117,255),
};
+std::array<std::array<int,3>,efc::diamondsNumber> DIAMONDS_SETUP =
+{
+ {
+ {0,0,-1},{0,0,-1},
+ {1,0,-1},{1,0,-1},
+ {2,0,-1},{2,0,-1},
+ {3,0,-1},{3,0,-1},
+ {4,0,-1},{4,0,-1},{4,0,-1},{4,0,-1},{4,0,-1},{4,0,-1},
+
+ {0,1,-1},{0,1,-1},
+ {1,1,-1},{1,1,-1},
+ {2,1,-1},{2,1,-1},
+ {3,1,-1},{3,1,-1},
+ {4,1,-1},{4,1,-1},{4,1,-1},{4,1,-1},{4,1,-1},{4,1,-1},
+
+ {0,2,-1},{0,2,-1},
+ {1,2,-1},{1,2,-1},
+ {2,2,-1},{2,2,-1},
+ {3,2,-1},{3,2,-1},
+ {4,2,-1},{4,2,-1},{4,2,-1},{4,2,-1},{4,2,-1},{4,2,-1},
+
+ {0,3,-1},{0,3,-1},
+ {1,3,-1},{1,3,-1},
+ {2,3,-1},{2,3,-1},
+ {3,3,-1},{3,3,-1},
+ {4,3,-1},{4,3,-1},{4,3,-1},{4,3,-1},{4,3,-1},{4,3,-1},
+
+ }
+} ;
+
+
}
diff --git a/data.h b/data.h
index a47b530..bed5fdc 100644
--- a/data.h
+++ b/data.h
@@ -1,25 +1,25 @@
#ifndef DATA_H
#define DATA_H
#include <string>
#include <SFML/Graphics.hpp>
namespace efc {
-
extern std::string seasonsNames[4];
enum directions {
DIR_LEFT,
DIR_RIGHT,
DIR_UP,
DIR_DOWN
};
extern int terrainArray[24];
extern sf::Color playersColors[4];
extern std::array<std::array<int,2>,256> boards;
- extern int possibleExits[4];
-
-
-
+ extern int possibleExits[4]; // number of portal's exit where player stops to play
+ const static int diamondsNumber = 56; // number of all cards / diamonds on the board
+ extern std::array<std::array<int,3>,efc::diamondsNumber> DIAMONDS_SETUP;
+ extern std::array<std::array<int,39>,4> occupiedFields;
+ const static int numberSteps = 39;
}
#endif // DATA_H
diff --git a/game.cpp b/game.cpp
index 4e5aa1a..6a49c23 100644
--- a/game.cpp
+++ b/game.cpp
@@ -1,750 +1,752 @@
#include "game.h"
namespace efc {
int initScreenX = 1360;
int initScreenY = 768;
int currentSeason = 0;
int month = 0;
void Game::initBoard()
{
// Grass tile starts at 342 and has 11 tiles
// int level[256];
// int level[256];
// Structure of the board
/*
{
342, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
80, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3 }
*/
// Fill the array
for (int i=0;i<256;i++)
{
int grass = (rand() % 10) + 1;
level[i] = 342 + grass;
level[i] = level[i];
}
// level[0] = 441;
// level[240] = 0;
// level[255] = 0;
// level[15] = 0;
level[8] = 813;
level[24] = 803;
level[40] = 803;
level[56] = 803;
level[72] = 803;
level[88] = 801;
level[167] = 809;
level[183] = 803;
level[199] = 803;
level[215] = 803;
level[231] = 803;
level[247] = 812;
level[112] = 811;
for (int i=113;i<117;i++)
level[i] = 816;
level[117] = 815;
level[138] = 800;
for (int i=139;i<143;i++)
level[i] = 816;
level[143] = 814;
map.load(&textures, sf::Vector2u(efc::TILE_SIZE, efc::TILE_SIZE), level, efc::BOARD_SIZE, efc::BOARD_SIZE);
sfxClick.setBuffer(sfxClickBuffer);
sfxDone.setBuffer(sfxDoneBuffer);
spriteBackground.setTexture(textureBackground);
spriteBackgroundDark.setTexture(textures.backgroundDark);
spriteBackgroundDark.setPosition(0,0);
gameBackground.setTexture(textures.textureGameBackground);
// viewTiles.setViewport(sf::FloatRect(0.04f,0.060f, 1.0f, 1.0f));
viewTiles.setViewport(sf::FloatRect(0.15f,0.1f, 1.0f, 1.0f));
viewGui.setViewport(sf::FloatRect(0.806f,0.066f, 1, 1));
selector.changeColor(turn); //This is only for the test TODO: remove
groupHud.setFont(&gameFont);
groupHud.setSeason(currentSeason);
groupHud.setRoundName(roundNumber);
sf::IntRect seasonsRect[4] = {sf::IntRect(0,0,255,255), sf::IntRect(256,0,512,255), sf::IntRect(0,255, 255, 512), sf::IntRect(255,255,512, 512)};
sf::Sprite season1;
season1.setTexture(textures.textureSeasons);
season1.setTextureRect(seasonsRect[0]);
season1.setPosition(0,400);
season1.scale(sf::Vector2f(0.25f, 0.25f));
season1.move(37.5, 30.5);
season1.setColor(sf::Color(0,255,0,80));
seasons[0] = season1;
sf::Sprite season2;
season2.setTexture(textures.textureSeasons);
season2.setTextureRect(seasonsRect[1]);
season2.setPosition(0,400);
season2.scale(sf::Vector2f(0.25f, 0.25f));
season2.move(37.5, 30.5);
season2.setColor(sf::Color(200,200,50,80));
seasons[1] = season2;
sf::Sprite season3;
season3.setTexture(textures.textureSeasons);
season3.setTextureRect(seasonsRect[2]);
season3.setPosition(0,400);
season3.scale(sf::Vector2f(0.25f, 0.25f));
season3.move(37.5, 30.5);
season3.setColor(sf::Color(90,90,255,80));
seasons[2] = season3;
sf::Sprite season4;
season4.setTexture(textures.textureSeasons);
season4.setTextureRect(seasonsRect[3]);
season4.setPosition(0,400);
season4.scale(sf::Vector2f(0.25f, 0.25f));
season4.move(37.5, 30.5);
season4.setColor(sf::Color(255,0,0,80));
seasons[3] = season4;
PlayerHud playerHud1(&textures, std::rand() % 80, &gameFont, 32,0);
PlayerHud playerHud2(&textures, std::rand() % 30, &gameFont, 32,1);
PlayerHud playerHud3(&textures, std::rand() % 60, &gameFont, 32,2);
PlayerHud playerHud4(&textures, std::rand() % 50, &gameFont, 32,3);
players[0] = playerHud1;
players[1] = playerHud2;
players[3] = playerHud3;
players[2] = playerHud4;
players[0].setActive(true);
setCurrentNeighbours();
// roundDice.throwDiceSix();
diceResultPlayer = 6;
players[turn].characters[0].diceResult = diceResultPlayer;
roundDice.setColor(turn);
}
void Game::setCurrentNeighbours ()
{
currentNeighbours = players[turn].getNeighbours();
}
void Game::loadAssets()
{
if (!textureFaces.loadFromFile("assets/img/faces.jpg"))
std::exit(1);
if (!textureTiles.loadFromFile("assets/img/zw-tilesets/_MAP.png"))
std::exit(1);
if (!gameFont.loadFromFile("assets/fnt/metal-mania.regular.ttf"))
{
std::exit(1);
}
if (!menuFont.loadFromFile("assets/fnt/metal-macabre.regular.ttf"))
{
std::exit(1);
}
if (!textureBackgroundArt.loadFromFile("assets/img/background_land.png"))
std::exit(1);
spriteBackgroundArt.setTexture(textureBackgroundArt);
if (!musicGame.openFromFile("assets/audio/game.ogg"))
std::exit(1);
if (!musicBackground.openFromFile("assets/audio/wind2.ogg"))
std::exit(1);
if (!musicMenu.openFromFile("assets/audio/menu.ogg"))
std::exit(1);
if (!sfxClickBuffer.loadFromFile("assets/audio/click.ogg"))
std::exit(1);
if (!sfxDoneBuffer.loadFromFile("assets/audio/done.ogg"))
std::exit(1);
if (!textureBackground.loadFromFile("assets/img/background.png"))
std::exit(1);
menuTxt.setFont(menuFont);
menuTxt.setCharacterSize(60);
menuTxt.setString(gameTitle);
int width = menuTxt.getLocalBounds().width;
int height = menuTxt.getLocalBounds().height;
menuTxt.setPosition(400-(width/2),300-(height/2)-150);
menuTxt.setColor(sf::Color(55, 255, 35, 85));
}
void Game::showMenu()
{
musicBackground.play();
musicBackground.setLoop(true);
menuBackground.setTexture(textures.textureMenu);
musicBackground.setVolume(7);
musicMenu.play();
musicMenu.setLoop(true);
currentState = state_menu;
}
void Game::hideMenu()
{
musicMenu.stop();
}
void Game::showGameBoard()
{
musicGame.setVolume(50);
musicGame.play();
musicGame.setLoop(true);
currentState = state_roll_dice;
}
void Game::endGame()
{
currentState = state_end_game;
musicBackground.stop();
}
void Game::handleLeftClick(sf::Vector2f pos,
sf::Vector2f posGui, sf::Vector2f posFull, int mousePos) {
std::cout << "mouse clicked mousePose " << mousePos << "dice " << diceResultPlayer << std::endl;
if (currentState==state_game)
{
std::array<int,2> movements = players[turn].getMovements(diceResultPlayer);
if ((mousePos==movements[0]) || (mousePos==movements[1]))
{
players[turn].setFigurePos(mousePos);
int *possibleExit = std::find(std::begin(efc::possibleExits),
std::end(efc::possibleExits), mousePos);
if (possibleExit != efc::possibleExits+4) {
std::cerr << "Found hahahah" << mousePos << std::endl;
players[turn].done=true;
numberFinishedPlayers += 1;
if (numberFinishedPlayers > 3)
endGame();
} else {
std::cerr << "Not found" << std::endl;
}
nextPlayer();
}
std::string resultCommand = players[turn].getElem(posGui);
command(resultCommand);
if (currentNeighbours.find(mousePos) != currentNeighbours.end())
{
if ((!guiSelectBuilding.active) && (showPlayerBoardElems))
{
float hover_x =posFull.x;
float hover_y = posFull.y;
if (pos.y > 290)
hover_y = hover_y - 100;
if (pos.x > 240)
hover_x = hover_x - 150;
if (hover_x>250)
hover_x = 249.0f;
if (hover_x<0)
hover_x = 1.0f;
if (hover_y>300)
hover_y = 299.0f;
if (hover_y<0)
hover_y = 1.0f;
selectedPos = mousePos;
// Currently we are not goint to use it.
// std::cout << hover_x << " " << hover_y << std::endl;
// guiSelectBuilding.setPosition(guiStartPos[turn][0],guiStartPos[turn][1]);
// guiSelectBuilding.active = true;
// sfxClick.play();
// currentState = state_gui_elem;
}
}
}
else if (currentState==state_roll_dice)
{
sf::IntRect diceRect(roundDice.spriteDice.getGlobalBounds());
if (diceRect.intersects(sf::IntRect(posFull.x, posFull.y, 1, 1)))
{
diceResultPlayer = roundDice.throwDiceSix();
players[turn].characters[0].diceResult=diceResultPlayer;
currentState=state_game;
}
}
else if (currentState==state_gui_elem)
{
std::string resultCommand = guiSelectBuilding.getElem(posFull);
if (resultCommand.find("elem_")==0)
{
std::string resultCommandWrapped = "build_" + resultCommand;
command(resultCommandWrapped);
} else if (resultCommand.find("close_gui")==0)
{ command(resultCommand);}
}
if (currentState==state_menu)
{
hideMenu();
showGameBoard();
}
if (currentState==state_gui_end_round)
{
std::string resultCommand = guiRoundDice.getElem(pos);
command(resultCommand);
}
}
void Game::hideGameBoard()
{
musicGame.play();
}
Game::Game():
screenSize(efc::initScreenX,efc::initScreenY),
window(sf::VideoMode(efc::initScreenX, efc::initScreenY), "Pagan Board"),
viewFull(sf::FloatRect(00, 00, screenSize.x, screenSize.y)),
viewGui(sf::FloatRect(00, 00, screenSize.x, screenSize.y)),
viewTiles(sf::FloatRect(0, 0, 1360, 768)),
selector(efc::TILE_SIZE),
guiSelectBuilding(&textures),
character(&textures, 3),
turn(0),
gameTitle("pagan board"),
roundDice(players),
roundNumber(1),
- guiRoundDice(&textures)
+ guiRoundDice(&textures),
+ boardDiamonds(&textures)
{
int gWidth = guiSelectBuilding.rectangle.getLocalBounds().width;
int gHeight = guiSelectBuilding.rectangle.getLocalBounds().height;
int borderLeft = 31;
int borderRight = 28;
int borderTop = 39;
int borderBottom = 39;
int guiWidth = 128;
int guiStartPosTmp[4][2] = {
{borderLeft+3,borderTop+2},
{screenSize.x - guiWidth - borderRight - gWidth-4,borderTop+2},
{borderLeft+3,screenSize.y-gHeight-borderBottom-4} ,
{screenSize.x - guiWidth - borderRight - gWidth-4,
screenSize.y-gHeight-borderBottom-4}};
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
guiStartPos[i][j] = guiStartPosTmp[i][j];
}
numberFinishedPlayers = 0;
sf::Clock frameClock;
guiRoundDice.active = true;
showPlayerBoardElems = false;
window.setVerticalSyncEnabled(true);
Hover hover;
GuiWindow guiWindow(&textures);
std::srand (time(NULL));
loadAssets();
initBoard();
showMenu();
// run the main loop
while (window.isOpen())
{
sf::Time frameTime = frameClock.restart();
std::string resultCommand = "";
// handle events
sf::Event event;
while (window.pollEvent(event))
{
sf::Vector2i localPositionTmp = sf::Mouse::getPosition(window);
sf::Vector2f localPosition = window.mapPixelToCoords(localPositionTmp,viewTiles);
sf::Vector2f localPositionGui = window.mapPixelToCoords(localPositionTmp,viewGui);
sf::Vector2f localPositionFull = window.mapPixelToCoords(localPositionTmp,viewFull);
int mousePosX = (int)localPosition.x / efc::TILE_SIZE;
int mousePosY = (int)localPosition.y / efc::TILE_SIZE;
int mousePos = efc::transCords(sf::Vector2i(mousePosX, mousePosY));
if(event.type == sf::Event::Closed)
window.close();
if (currentState==state_gui_elem)
{
resultCommand = guiSelectBuilding.getElem(localPositionFull);
showPlayerBoardElems = false;
if (resultCommand.find("elem_")==0)
command(resultCommand);
else
command("hide_gui_elem_description");
}
if (currentState==state_game)
{
if ((localPosition.x>efc::TILE_SIZE*efc::BOARD_SIZE) || (localPosition.x<0) || (localPosition.y>efc::TILE_SIZE*efc::BOARD_SIZE) || (localPosition.y<0))
{
showPlayerBoardElems = false;
players[turn].elems.displayNeighbours = false;
} else {
showPlayerBoardElems = true;
players[turn].elems.displayNeighbours = true;
}
}
if (event.type == sf::Event::MouseButtonReleased)
{
if (event.mouseButton.button == sf::Mouse::Left)
handleLeftClick(localPosition, localPositionGui,
localPositionFull, mousePos);
}
if ((localPosition.x>=0) && (localPosition.y>=0) && (localPosition.x<=efc::BOARD_SIZE*efc::TILE_SIZE) && (localPosition.y<=efc::BOARD_SIZE*efc::TILE_SIZE))
{
selector.setPosition((int) (localPosition.x / efc::TILE_SIZE)*efc::TILE_SIZE, ((int) localPosition.y / efc::TILE_SIZE)*efc::TILE_SIZE);
}
}
update(frameTime);
render();
}
}
void Game::update(sf::Time frameTime) {
if (currentState==state_game)
{
std::array<int,2> currentMovements = players[turn].getMovements(diceResultPlayer);
if (currentMovements[0]>-1)
{
prevRotateElem.spriteRotate.setPosition(players[turn].characters[0].leftChar.getPosition());
prevRotateElem.spriteRotate.move(4,16);
prevRotateElem.update(frameTime);
prevRotateElem.setColor(turn);
}
if (currentMovements[1]>-1)
{
nextRotateElem.spriteRotate.setPosition(players[turn].characters[0].rightChar.getPosition());
nextRotateElem.spriteRotate.move(4,16);
nextRotateElem.update(frameTime);
nextRotateElem.setColor(turn);
}
}
for (int i=0;i<4;i++)
{
players[i].play();
}
for (int i=0;i<4;i++)
{
players[i].update(frameTime, busyTiles);
}
}
void Game::nextRound() {
turn = 0;
std::string result = roundDice.drawRound();
roundNumber += 1;
// std::cout << "END OF ROUND " << roundNumber << " " << result << std::endl;
month++;
if (month==13)
month=1;
if (month%4==0)
currentSeason++;
if (currentSeason>3)
currentSeason=0;
if (players[turn].done==true)
nextPlayer();
// command(result);
}
void Game::nextPlayer(){
if (numberFinishedPlayers==4)
{
std::cout << "Everybody Finished!!!" << std::endl;
endGame();
}
if (turn<4)
players[turn].updatePlayer();
else
nextRound();
turn++;
if ((players[turn].done==true) && (turn<4))
{
std::cout << "Player " << turn << " is done" << std::endl;
nextPlayer();
}
if ((turn==4) || (turn>4))
{
nextRound();
}
selector.changeColor(turn);
for (int i=0;i<4;i++)
{
if (i==turn)
{
players[i].setActive(true);
currentNeighbours = players[i].getNeighbours();
}
else
players[i].setActive(false);
}
sfxClick.play();
// roundDice.throwDiceSix();
// diceResultPlayer = roundDice.throwDiceSix();
diceResultPlayer = 6;
roundDice.setDiceTexture(diceResultPlayer);
// std::cout << "DEBUG " << turn << " "<< diceResultPlayer << std::endl;
players[turn].characters[0].diceResult = diceResultPlayer;
// std::cout << roundNumber << " " << roundNumber % 16 << std::endl;
groupHud.setRoundName(roundNumber);
groupHud.setSeason(currentSeason);
groupHud.setMonthName(month%4);
// setBusyTiles();
currentState = state_roll_dice;
roundDice.setColor(turn);
}
void Game::drawPlayersGui(){
for (int i=0;i<4;i++)
{
window.draw(players[i]);
}
window.draw(seasons[currentSeason]);
}
void Game::drawSquares() {
if (showPlayerBoardElems)
{
window.draw(selector);
}
}
void Game::drawBaseGame()
{
window.setView(viewTiles);
// window.draw(map);
for (int i=0;i<4;i++)
{
window.draw(players[i].elems);
}
drawSquares();
window.setView(viewGui);
drawPlayersGui();
window.setView(viewTiles);
}
void Game::drawCharacters(){
// window.setView(viewFull);
window.setView(viewTiles); // Yeah Katia's inspiration
window.draw(gameBackground);
window.setView(viewFull);
window.draw(spriteBackgroundArt);
window.draw(roundDice.spriteDice);
window.setView(viewTiles);
drawSquares();
if (currentState==state_game)
{
std::array<int,2> currentMovements = players[turn].characters[0].getMovements(diceResultPlayer);
if (currentMovements[1]>-1)
window.draw(nextRotateElem);
if (currentMovements[0]>-1)
window.draw(prevRotateElem);
}
for (int i=0;i<4;i++)
{
for (auto&& j: players[i].characters)
{
if (currentState==state_game)
j.drawMovements = true;
else
j.drawMovements = false;
window.draw(j);
}
}
}
void Game::render()
{
window.clear();
if (currentState==state_game)
{
window.setView(viewFull);
window.draw(spriteBackgroundDark);
window.setView(viewTiles);
drawBaseGame();
drawCharacters();
+ window.draw(boardDiamonds);
} else if (currentState==state_roll_dice) {
window.setView(viewFull);
window.draw(spriteBackgroundDark);
window.setView(viewTiles);
drawBaseGame();
drawCharacters();
} else if (currentState==state_gui_elem) {
window.setView(viewFull);
window.draw(spriteBackgroundDark);
drawBaseGame();
drawCharacters();
window.draw(guiSelectBuilding);
} else if (currentState==state_menu) {
window.draw(menuBackground);
window.draw(menuTxt);
window.draw(groupHud);
window.setView(viewFull);
} else if (currentState==state_gui_end_round){
window.setView(viewFull);
window.draw(spriteBackgroundDark);
drawBaseGame();
window.draw(guiRoundDice);
}
window.setView(viewFull);
window.draw(groupHud);
window.display();
}
void Game::command(std::string command){
// std::cout << command << std::endl;
if (command=="close_gui")
{
guiSelectBuilding.active = false;
currentState=state_game;
sfxClick.play();
}
if (command=="hide_gui_elem_description")
{
if (currentState==state_gui_elem) {
guiSelectBuilding.descriptionActive = false;
}
}
if (command.find("end_of_round")==0)
{
std::string subResult = command.substr(13);
guiRoundDice.active = true;
guiRoundDice.setTitle(subResult);
currentState = state_gui_end_round;
}
// if (command.find("elem_")==0)
// {
// if (currentState==state_gui_elem)
// {
// int buildingType = std::stoi(command.substr(5));
// std::string descTxt = textures.tilesTxt[buildingType];
// char priceTxtChar [100];
// std::string priceTxt = priceTxtChar;
// char costTxtChar [100];
// std::string costTxt = costTxtChar;
// guiSelectBuilding.setDescriptionTxt(priceTxt + costTxt + "\n"+descTxt);
// guiSelectBuilding.descriptionActive = true;
// }
// }
if (command=="end_turn")
nextPlayer();
// if (command.find("build_")==0)
// {
// int buildingType = std::stoi(command.substr(11));
// bool purchaseResult = players[turn].addElem(selectedPos, buildingType);
// if (purchaseResult)
// {
// currentState = state_game;
// setCurrentNeighbours();
// guiSelectBuilding.active = false;
// sfxDone.play();
// }
// }
}
sf::Vector2f Game::getMousePos(){
sf::Vector2i mousePosTmp(sf::Mouse::getPosition(window));
sf::Vector2f mousePosition(window.mapPixelToCoords(mousePosTmp,viewTiles));
return mousePosition;
}
void Game::setBusyTiles() {
busyTiles.clear();
for (int i: efc::terrainArray)
{
busyTiles.insert(i);
}
for (int i=0;i<4;i++)
{
for (int j:players[i].getBusy())
{
busyTiles.insert(j);
}
}
}
}
diff --git a/game.h b/game.h
index 61926a3..3028ac1 100644
--- a/game.h
+++ b/game.h
@@ -1,170 +1,170 @@
#ifndef GAME_H
#define GAME_H
#include <stdlib.h>
#include <iostream>
#include <time.h> /* time */
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "tilemap.h"
#include "selector.h"
#include "playerhud.h"
#include "textureholder.h"
#include "hover.h"
#include "guichoosebuilding.h"
#include "guiwindow.h"
#include "rounddice.h"
#include "guirounddice.h"
#include "grouphud.h"
#include "animatedsprite.h"
#include "character.h"
#include "rotateelem.h"
-#include "boarddiamond.h"
+#include "boarddiamondseq.h"
namespace efc {
extern int initScreenX;
extern int initScreenY;
class Game
{
private:
sf::Vector2i screenSize;
public:
Game();
sf::RenderWindow window;
sf::View viewFull;
sf::View viewGui;
sf::View viewTiles;
private:
void initBoard();
void loadAssets();
void drawPlayersGui();
void drawSquares();
void drawMenu();
sf::Vector2f getMousePos();
enum states {
state_init,
state_menu,
state_roll_dice,
state_game,
state_gui_elem,
state_select_building,
state_gui_end_round,
state_end_game,
state_quit
};
states currentState;
sf::Texture textureBackground;
sf::Sprite spriteBackground;
sf::Sprite gameBackground;
sf::Sprite spriteBackgroundDark;
sf::Texture textureBackgroundArt;
sf::Sprite spriteBackgroundArt;
sf::Texture textureTiles;
sf::Texture textureFaces;
sf::Font gameFont;
sf::Font menuFont;
sf::Text menuTxt;
TileMap map;
PlayerHud players[4];
int mapSize;
int level[256];
int levelElems[256];
TextureHolder textures;
std::set<int> currentNeighbours;
void command(std::string command);
int selectedPos;
Selector selector;
GuiChooseBuilding guiSelectBuilding;
Character character;
int turn;
void update(sf::Time frameTime);
void render();
std::string gameTitle;
RoundDice roundDice;
int roundNumber;
GuiRoundDice guiRoundDice;
void setCurrentNeighbours ();
void nextPlayer();
void nextRound();
sf::Sprite menuBackground;
sf::Sprite seasons[4];
//int currentSeason = 0;
sf::Music musicGame;
sf::Music musicBackground;
sf::Music musicMenu;
sf::SoundBuffer sfxClickBuffer;
sf::Sound sfxClick;
sf::SoundBuffer sfxDoneBuffer;
sf::Sound sfxDone;
void showMenu();
void hideMenu();
void showGameBoard();
void hideGameBoard();
GroupHud groupHud;
bool showPlayerBoardElems;
void drawBaseGame();
int month;
Animation walkingAnimationDown;
Animation walkingAnimationUp;
Animation walkingAnimationLeft;
Animation walkingAnimationRight;
Animation* currentAnimation;
AnimatedSprite animatedSprite;
void drawCharacters();
void handleLeftClick(sf::Vector2f pos,
sf::Vector2f posGui, sf::Vector2f posFull, int mousePos);
int guiStartPos[4][2];
std::set<int> busyTiles;
void setBusyTiles();
int diceResultPlayer;
int numberFinishedPlayers;
RotateElem nextRotateElem;
RotateElem prevRotateElem;
void endGame();
- sf::Sprite boardDiamonds[4];
+ BoardDiamondSeq boardDiamonds;
};
}
#endif // GAME_H
diff --git a/playerhud.cpp b/playerhud.cpp
index c01ddfe..6d5f08b 100644
--- a/playerhud.cpp
+++ b/playerhud.cpp
@@ -1,323 +1,242 @@
#include "playerhud.h"
#include "textureholder.h"
#include "boardelem.h"
bool PlayerHud::addElem(int pos, int type) {
int price = textures->tilesDescription[type][0];
if (price<=cash)
{
efc::BoardElem startElem(textures, pos,type);
startElem.setColor(efc::playersColors[this->pos]);
elems.items.push_back(startElem);
elems.items_map.insert({pos, startElem});
cash -= price;
updateTxt();
// characters.push_back(Character (this->textures, this->pos));
return true;
}
return false;
}
std::set<int> PlayerHud::getTerrainSet(){
std::set<int> terrain;
for (int i: efc::terrainArray)
{
// std::cout << i << std::endl;
terrain.insert(i);
}
return terrain;
}
std::set<int> PlayerHud::getBusy(){
std::set<int> busyTiles;
for (std::pair<int, efc::BoardElem> i: elems.items_map)
{
busyTiles.insert(i.first);
}
return busyTiles;
}
std::set<int> PlayerHud::getNeighbours(){
std::set<int> neighbours;
for (std::pair<int, efc::BoardElem> i: elems.items_map)
{
std::set<int> terrain = getTerrainSet();
std::set<int> neighboursVector(efc::getNeighbours(i.second.pos));
for (int j: neighboursVector)
{
if ((elems.items_map.count(j) == 0) && (terrain.count(j)==0))
{
// std::cout << j << " " << terrain.count(j) << std::endl;
neighbours.insert(j);
}
}
}
// // Fill in s1 and s2 with values
// std::set<int> result;
// std::set_difference(neighbours.begin(), neighbours.end(), terrain.begin(), terrain.end(),
// std::inserter(result, result.end()));
// for (int i: result)
// {
// std::cout << i << std::endl;
// }
return neighbours;
}
void PlayerHud::updateTxt(){
txtCash.setString( "Cash: " + std::to_string(cash));
txtFood.setString( "Food: " + std::to_string(food));
txtEnergy.setString("Enrg: " + std::to_string(energy));
txtFaith.setString( "Gods: " + std::to_string(faith));
}
void PlayerHud::updatePlayer(){
for (const efc::BoardElem &i: elems.items)
{
int cashUpd = textures->tilesDescription[i.type][1];
int foodUpd = textures->tilesDescription[i.type][3];
int enrgUpd = textures->tilesDescription[i.type][5];
int faithUpd = textures->tilesDescription[i.type][7];
cash += cashUpd;
energy += enrgUpd;
food += foodUpd;
faith += faithUpd;
updateTxt();
}
}
PlayerHud::PlayerHud()
{
}
void PlayerHud::setActive(bool newState){
active = newState;
elems.active = newState;
for (auto&& i: characters)
{
i.active = newState;
}
}
PlayerHud::PlayerHud(TextureHolder *textures, int faceNumber, sf::Font *gameFont, int faceSize, int pos)
{
static int startPlayers[4] = {0,15,240,255};
done = false;
active = false;
this->textures = textures;
Character character(this->textures, pos);
characters.push_back(Character (this->textures, pos));
efc::BoardElem startElem(textures, startPlayers[pos],444);
startElem.setColor(efc::playersColors[pos]);
elems.items.push_back(startElem);
elems.items_map.insert({startPlayers[pos], startElem});
this->faceSize = faceSize;
spriteFace.setTexture(textures->textureFaces);
this->pos = pos;
symbol.setTexture(this->textures->textureSymbols);
sf::IntRect symbolsRect[4] = {sf::IntRect(0,0,255,255), sf::IntRect(256,0,512,255), sf::IntRect(0,255, 255, 512), sf::IntRect(255,255,512, 512)};
symbol.setTextureRect(symbolsRect[pos]);
symbol.setScale(sf::Vector2f(0.2f, 0.20f));
symbol.setColor(sf::Color(25, 25, 25, 105));
symbol.setPosition(60, (pos*100)+40);
food = 0;
cash = 20;
energy = 0;
faith = 0;
int x = faceNumber % 10;
int y = (int) faceNumber /10;
txtCash.setFont(*gameFont);
txtFood.setFont(*gameFont);
txtEnergy.setFont(*gameFont);
txtFaith.setFont(*gameFont);
txtNextRound.setFont(*gameFont);
txtNextRound.setString("End Turn");
-// txtNextRound.setScale(sf::Vector2f(0.25f, 1.f));
txtNextRound.setCharacterSize(12);
txtNextRound.setPosition(40,(pos*100)+10);
- txtCash.setPosition(1,(pos*100)+40);
- // txtCash.setString("Cash: " + std::to_string(cash));
- txtCash.setCharacterSize(10);
-// txtCash.setScale(sf::Vector2f(0.25f, 1.f));
- txtFood.setPosition(1,(pos*100)+55);
- // txtFood.setString("Food: " + std::to_string(food));
- txtFood.setCharacterSize(10);
-// txtFood.setScale(sf::Vector2f(0.25f, 1.f));
-
- txtEnergy.setPosition(1,(pos*100)+70);
- // txtEnergy.setString("Enrg: " + std::to_string(energy));
- txtEnergy.setCharacterSize(10);
-// txtEnergy.setScale(sf::Vector2f(0.25f, 1.f));
-
- txtFaith.setPosition(1,(pos*100)+85);
- // txtEnergy.setString("Enrg: " + std::to_string(energy));
- txtFaith.setCharacterSize(10);
-// txtFaith.setScale(sf::Vector2f(0.25f, 1.f));
- updateTxt();
-
- spriteFace.setTextureRect(sf::IntRect(x*faceSize, y*faceSize, faceSize, faceSize));
-// spriteFace.setScale(sf::Vector2f(0.25f, 1.f));
- spriteFace.setPosition(0,pos*100);
-
-
- rectangle.setSize(sf::Vector2f((this->faceSize)*7, this->faceSize));
- rectangle2.setSize(sf::Vector2f((this->faceSize)*7, (this->faceSize*2)+3));
- rectangle.setFillColor(efc::playersColors[pos]);
- if (pos==0)
- {
- rectangle.setFillColor(efc::playersColors[pos]);
-// rectangle2.setFillColor(sf::Color(100, 100, 150,38));
-// rectangle.setOutlineColor(sf::Color(0,0,128,68));
- }
- else if (pos==1)
- {
-// rectangle.setFillColor(sf::Color(50, 150, 50,68));
-// rectangle2.setFillColor(sf::Color(100, 150,100,38));
-// rectangle.setOutlineColor(sf::Color(0,128,0,68));
- }
-
- else if (pos==2)
- {
-// rectangle.setFillColor(sf::Color(150, 50, 50,68));
-// rectangle2.setFillColor(sf::Color(150, 100,100,38));
-// rectangle.setOutlineColor(sf::Color(128,0,0,68));
- }
- else if (pos==3)
- {
-// rectangle.setFillColor(sf::Color(150, 150, 150,68));
-// rectangle2.setFillColor(sf::Color(200, 200,200,38));
-// rectangle.setOutlineColor(sf::Color(128,128,128,68));
- }
-
-
-// rectangle.setOutlineThickness(1);
- rectangle.setPosition(0, pos*100);
- rectangle2.setPosition(0, (pos*100)+faceSize+1);
buttons.insert({"end_turn",rectangle});
}
std::string PlayerHud::getElem(sf::Vector2f mousePosition) {
std::string result = "";
sf::Vector2f hoverPos = getPosition();
for (std::pair<std::string, sf::RectangleShape> i: buttons)
{
sf::FloatRect spriteBounds = i.second.getLocalBounds();
sf::FloatRect closeRect;
closeRect.left = i.second.getPosition().x;
closeRect.top = i.second.getPosition().y;
closeRect.width = spriteBounds.width;
closeRect.height = spriteBounds.height;
-// std::cout << closeRect.left << " " << closeRect.top << " " << closeRect.width << " " << closeRect.height
-// << hoverPos.x << " " << hoverPos.y << " OK"
-// << std::endl;
+
if (closeRect.contains(mousePosition.x - hoverPos.x,mousePosition.y - hoverPos.y))
{
-
return i.first;
}
}
return result;
}
void PlayerHud::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
- // // apply the transform
states.transform *= getTransform();
- // Color rectangles making the gui on the right side
- // sf::RectangleShape rectangle(sf::Vector2f(faceSize, faceSize));
- // sf::RectangleShape rectangle2(sf::Vector2f(faceSize, (faceSize*2)+3));
-
-
-
-
- target.draw(rectangle, states);
- target.draw(rectangle2, states);
- target.draw(txtCash, states);
- target.draw(txtFood, states);
- target.draw(txtEnergy, states);
- target.draw(txtFaith, states);
-
if (active)
target.draw(txtNextRound, states);
- target.draw(symbol, states);
- target.draw(spriteFace, states);
+
}
void PlayerHud::play()
{
for (auto&& i: characters)
{
-
i.play();
-}
-
+ }
}
void PlayerHud::update(sf::Time deltaTime, std::set<int>& busyTiles)
{
for (auto&& i: characters)
{
sf::Vector2f movement(0.f, 0.f);
if (i.currentAnimationIndex==efc::DIR_LEFT)
movement = sf::Vector2f (-10.f, 0.f);
else if (i.currentAnimationIndex==efc::DIR_RIGHT)
movement = sf::Vector2f (10.f, 0.f);
else if (i.currentAnimationIndex==efc::DIR_UP)
movement = sf::Vector2f (0.f, -10.f);
else if (i.currentAnimationIndex==efc::DIR_DOWN)
movement = sf::Vector2f (0.f, 10.f);
-
// i.move(movement * deltaTime.asSeconds());
i.update(deltaTime, busyTiles);
}
}
std::array<int,2> PlayerHud::getMovements(int diceResult)
{
return characters[0].getMovements(diceResult);
}
void PlayerHud::setFigurePos(int pos)
{
characters[0].setBoardPosition(pos);
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Feb 2, 8:56 PM (2 d, 8 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55540
Default Alt Text
(45 KB)

Event Timeline