commit 092bdebe
Added the beginning of a function to play replays! Also reformatted the source
Changed files
diff --git a/source/code/BlockGame.cpp b/source/code/BlockGame.cpp
index b8e10be..6ff4914 100644
--- a/source/code/BlockGame.cpp
+++ b/source/code/BlockGame.cpp
@@ -52,7 +52,7 @@ static string itoa2(int num) {
/**
* This function tells how long the game may pause the rise of the blocks.
* This decreases as the game progresses.
- * @param stops In out variable. If larger than the max allowed
+ * @param stops In out variable. If larger than the max allowed
* @param ticks Ticks since the game was started
* @param gameStartedAt Tick the game was started at.
*/
@@ -62,7 +62,7 @@ static void capMaxStops(int& stops, unsigned int ticks, unsigned int gameStarted
return;
}
unsigned int gameTime = gameStartedAt - ticks;
-
+
int maxSeconds = 10-( (gameTime/1000) % 30 );
if (maxSeconds < 3) {
maxSeconds = 1;
@@ -234,7 +234,6 @@ bool BlockGame::GetIsWinner() const {
return hasWonTheGame;
}
-
void BlockGame::NewGame(const BlockGameStartInfo& s) {
replayInfo.startInfo = s;
replayInfo.actions.clear();
@@ -277,7 +276,7 @@ void BlockGame::NewGame(const BlockGameStartInfo& s) {
}
}
for (int j=0; j<6; j++) {
- board[j][0] = 5;
+ board[j][0] = 5;
}
}
this->singlePuzzle = s.singlePuzzle;
@@ -1832,7 +1831,7 @@ void BlockGame::DoAction (const BlockGameAction& action) {
}
if (action.action == BlockGameAction::Action::UPDATE && replayInfo.actions.size() > 0 && replayInfo.actions.back().action == action.action) {
replayInfo.actions.back() = action;
- }
+ }
else {
replayInfo.actions.push_back(action);
}
@@ -1894,7 +1893,7 @@ void BlockGame::PopSendGarbage(std::vector<GarbageStruct>& poppedData) {
this->garbageSendQueue.clear();
}
-void BlockGame::GetMouseCursor(bool& pressed, int& x, int&y) const {
+void BlockGame::GetMouseCursor(bool& pressed, int& x, int& y) const {
if (mouse_cursorx < 0 || mouse_cursory < 0 || mouse_cursorx >=6 || mouse_cursory > 13) {
pressed = false;
x = 0;
@@ -1913,7 +1912,7 @@ void BlockGame::MouseDown(int x, int y) {
}
mouse_cursorx = x;
mouse_cursory = y;
-}
+}
void BlockGame::MouseMove(int x) {
if (AI_Enabled) {
diff --git a/source/code/MenuSystem.cpp b/source/code/MenuSystem.cpp
index b2b599e..ffe826f 100644
--- a/source/code/MenuSystem.cpp
+++ b/source/code/MenuSystem.cpp
@@ -90,19 +90,19 @@ bool Button::isPopOnRun() const {
return popOnRun;
}
-static void drawToScreen(const Button &b) {
+static void drawToScreen(const Button& b) {
if (b.marked) {
globalData.spriteHolder->GetSprite(menu_marked).Draw(globalData.screen, SDL_GetTicks(), b.x, b.y);
}
else {
globalData.spriteHolder->GetSprite(menu_unmarked).Draw(globalData.screen, SDL_GetTicks(), b.x, b.y);
}
-
+
standardButton.thefont->draw(globalData.screen, b.x+standardButton.xsize/2,b.y+standardButton.ysize/2-standardButton.thefont->getHeight("%s", b.label.c_str())/2, NFont::CENTER, "%s", b.label.c_str());
}
-static bool isClicked(const Button &b, int x,int y) {
+static bool isClicked(const Button& b, int x,int y) {
if ( x >= b.x && y >= b.y && x<= b.x+standardButton.xsize && y <= b.y + standardButton.ysize) {
return true;
}
@@ -302,7 +302,7 @@ void Menu::Draw(SDL_Renderer* target) {
placeButtons();
drawSelf(target);
}
-void Menu::ProcessInput(const SDL_Event& event, bool &processed) {
+void Menu::ProcessInput(const SDL_Event& event, bool& processed) {
if (isUpEvent(event)) {
marked--;
if (marked<0) {
diff --git a/source/code/ReplayPlayer.cpp b/source/code/ReplayPlayer.cpp
new file mode 100644
index 0000000..a01c583
--- /dev/null
+++ b/source/code/ReplayPlayer.cpp
@@ -0,0 +1,54 @@
+/*
+===========================================================================
+blockattack - Block Attack - Rise of the Blocks
+Copyright (C) 2005-2017 Poul Sander
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see http://www.gnu.org/licenses/
+
+Source information and contacts persons can be found at
+http://www.blockattack.net
+===========================================================================
+*/
+
+#include "ReplayPlayer.hpp"
+#include "global.hpp"
+#include "common.h"
+#include "MenuSystem.h"
+
+ReplayPlayer::ReplayPlayer() {
+}
+
+ReplayPlayer::~ReplayPlayer() {
+}
+
+bool ReplayPlayer::IsActive() {
+ return isActive;
+}
+
+void ReplayPlayer::Draw(SDL_Renderer* target) {
+ DrawBackground(target);
+}
+
+void ReplayPlayer::ProcessInput(const SDL_Event& event, bool& processed) {
+ UpdateMouseCoordinates(event, globalData.mousex, globalData.mousey);
+
+ if (isConfirmEvent(event) || isEscapeEvent(event)) {
+ isActive = false;
+ processed = true;
+ }
+}
+
+void ReplayPlayer::Update() {
+
+}
diff --git a/source/code/ReplayPlayer.hpp b/source/code/ReplayPlayer.hpp
new file mode 100644
index 0000000..0c3cc75
--- /dev/null
+++ b/source/code/ReplayPlayer.hpp
@@ -0,0 +1,44 @@
+/*
+===========================================================================
+blockattack - Block Attack - Rise of the Blocks
+Copyright (C) 2005-2017 Poul Sander
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see http://www.gnu.org/licenses/
+
+Source information and contacts persons can be found at
+http://www.blockattack.net
+===========================================================================
+*/
+
+#ifndef REPLAYPLAYER_HPP
+#define REPLAYPLAYER_HPP
+
+#include "sago/GameStateInterface.hpp"
+
+class ReplayPlayer : public sago::GameStateInterface {
+public:
+ ReplayPlayer();
+ ReplayPlayer(const ReplayPlayer& orig) = delete;
+ virtual ~ReplayPlayer();
+
+ bool IsActive() override;
+ void Draw(SDL_Renderer* target) override;
+ void ProcessInput(const SDL_Event& event, bool &processed) override;
+ void Update() override;
+private:
+ bool isActive = true;
+};
+
+#endif /* REPLAYPLAYER_HPP */
+
diff --git a/source/code/ScoresDisplay.cpp b/source/code/ScoresDisplay.cpp
index d21c826..dd6bad5 100644
--- a/source/code/ScoresDisplay.cpp
+++ b/source/code/ScoresDisplay.cpp
@@ -171,7 +171,7 @@ void ScoresDisplay::Draw(SDL_Renderer*) {
void ScoresDisplay::ProcessInput(const SDL_Event& event, bool& processed) {
UpdateMouseCoordinates(event, globalData.mousex, globalData.mousey);
-
+
if (isLeftEvent(event)) {
page++;
if (page>=numberOfPages) {
diff --git a/source/code/gamecontroller.cpp b/source/code/gamecontroller.cpp
index 0e05d9e..0ca6b98 100644
--- a/source/code/gamecontroller.cpp
+++ b/source/code/gamecontroller.cpp
@@ -54,14 +54,14 @@ static const char* GameControllerGetName(SDL_GameController* gamecontroller) {
static std::string GetGuidAsHex(const SDL_JoystickGUID& guid) {
std::string ret;
char buffer[3];
- for(size_t j = 0; j < 16; j++) {
+ for (size_t j = 0; j < 16; j++) {
snprintf(buffer, sizeof(buffer), "%02X", guid.data[j]);
ret += buffer;
}
return ret;
}
-static std::map<std::string, int> gamecontrollers_assigned;
+static std::map<std::string, int> gamecontrollers_assigned;
static int GetNextPlayerByGui(const SDL_JoystickGUID& guid) {
Config::getInstance()->setDefault("gc_AllToOnePlayer", "0");
@@ -75,7 +75,7 @@ static int GetNextPlayerByGui(const SDL_JoystickGUID& guid) {
int player = Config::getInstance()->getInt(configName) + gamecontrollers_assigned[guidAsHex];
gamecontrollers_assigned[guidAsHex]++; //Next controller with same guid should be assigned to different player.
//std::cout << "Guid: " << guidAsHex << "\n";
-
+
if (player%2==0) {
return 2; //Even number means player 2
}
@@ -95,7 +95,7 @@ void InitGameControllers() {
for (int i = 0; i < SDL_NumJoysticks(); ++i) {
if (SDL_IsGameController(i)) {
controller = SDL_GameControllerOpen(i);
- SDL_Joystick *j = SDL_GameControllerGetJoystick(controller);
+ SDL_Joystick* j = SDL_GameControllerGetJoystick(controller);
SDL_JoystickID instanceId = SDL_JoystickInstanceID(j);
SDL_JoystickGUID guid = SDL_JoystickGetGUID(j);
int assingToPlayer = GetNextPlayerByGui(guid);
diff --git a/source/code/global.hpp b/source/code/global.hpp
index 6dffbca..997dfb0 100644
--- a/source/code/global.hpp
+++ b/source/code/global.hpp
@@ -34,7 +34,7 @@ void MainMenu();
void ResetFullscreen();
void RunGameState(sago::GameStateInterface& state );
-enum class Gametype { SinglePlayerEndless=0, SinglePlayerTimeTrial=1, StageClear=2, Puzzle=3, SinglePlayerVs=4, TwoPlayerTimeTrial=10, TwoPlayerVs=11 };
+enum class Gametype { SinglePlayerEndless=0, SinglePlayerTimeTrial=1, StageClear=2, Puzzle=3, SinglePlayerVs=4, TwoPlayerTimeTrial=10, TwoPlayerVs=11, Replay=100 };
int runGame(Gametype gametype,int level);
bool OpenDialogbox(int x, int y, std::string& name, const std::string& header);
@@ -55,6 +55,7 @@ struct GlobalData {
bool MusicEnabled; //true if background music is enabled
bool SoundEnabled; //true if sound effects is enabled
bool bFullscreen; //true if game is running fullscreen
+ std::string replayArgument; //Name of the replay to play (if given as a commandline argument)
std::string player1name;
std::string player2name;
SDL_Renderer *screen = nullptr; //The whole screen;
diff --git a/source/code/levelselect.cpp b/source/code/levelselect.cpp
index 821d669..a6018c8 100644
--- a/source/code/levelselect.cpp
+++ b/source/code/levelselect.cpp
@@ -97,7 +97,7 @@ int PuzzleLevelSelect(int Type) {
SDL_Event event;
while ( SDL_PollEvent(&event) ) {
UpdateMouseCoordinates(event, globalData.mousex, globalData.mousey);
-
+
if ( event.type == SDL_QUIT ) {
Config::getInstance()->setShuttingDown(5);
levelNr = -1;
diff --git a/source/code/main.cpp b/source/code/main.cpp
index 5ba9a26..3a6ebb1 100644
--- a/source/code/main.cpp
+++ b/source/code/main.cpp
@@ -287,18 +287,18 @@ void DrawBackground(SDL_Renderer* target) {
* @param mousey
*/
void UpdateMouseCoordinates(const SDL_Event& event, int& mousex, int& mousey) {
- switch(event.type) {
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- mousex = event.button.x;
- mousey = event.button.y;
- break;
- case SDL_MOUSEMOTION:
- mousex = event.motion.x;
- mousey = event.motion.y;
- break;
- default:
- break;
+ switch (event.type) {
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ mousex = event.button.x;
+ mousey = event.button.y;
+ break;
+ case SDL_MOUSEMOTION:
+ mousex = event.motion.x;
+ mousey = event.motion.y;
+ break;
+ default:
+ break;
}
}
@@ -583,6 +583,7 @@ static TextManager theTextManager;
#include "BlockGameSdl.inc"
#include "sago/SagoMisc.hpp"
+#include "ReplayPlayer.hpp"
@@ -754,7 +755,6 @@ void DrawEverything(int xsize, int ysize,BlockGameSdl* theGame, BlockGameSdl* th
DrawIMG(stageBobble,globalData.screen,theGame->GetTopX()+280,theGame->GetTopY()+650+50*(theGame->GetStageClearLimit()-theGame->GetLinesCleared())-theGame->GetPixels()-1);
}
//player1 finnish, player2 start
- //DrawIMG(boardBackBack,globalData.screen,theGame2->GetTopX()-60,theGame2->GetTopY()-68);
if (!editorMode /*&& !singlePuzzle*/ ) {
/*
*If single player mode (and not VS)
@@ -1036,10 +1036,11 @@ static void ParseArguments(int argc, char* argv[], globalConfig& conf) {
("no-auto-scale", "Do not automatically auto scale")
("puzzle-level-file", boost::program_options::value<string>(), "Sets the default puzzle file to load")
("puzzle-single-level", boost::program_options::value<int>(), "Start the specific puzzle level directly")
+ ("play-replay", boost::program_options::value<string>(), "Start a replay")
("bind-text-domain", boost::program_options::value<string>(), SPrintStringF("Overwrites the bind text domain used for finding translations. "
- "Default: \"%s\"", LOCALEDIR).c_str())
+ "Default: \"%s\"", LOCALEDIR).c_str())
("homepath", boost::program_options::value<string>(), SPrintStringF("Set the home folder where settings are saved. The directory will be created if it does not exist."
- " Default: \"%s\"", getPathToSaveFiles().c_str()).c_str())
+ " Default: \"%s\"", getPathToSaveFiles().c_str()).c_str())
;
boost::program_options::variables_map vm;
@@ -1071,8 +1072,8 @@ static void ParseArguments(int argc, char* argv[], globalConfig& conf) {
}
if (vm.count("help")) {
cout << SPrintStringF("Block Attack - Rise of the blocks %s\n\n"
- "Block Attack - Rise of the Blocks is a puzzle/blockfall game inspired by Tetris Attack for the SNES.\n\n"
- "%s\n\n", VERSION_NUMBER, "www.blockattack.net");
+ "Block Attack - Rise of the Blocks is a puzzle/blockfall game inspired by Tetris Attack for the SNES.\n\n"
+ "%s\n\n", VERSION_NUMBER, "www.blockattack.net");
cout << "Usage: "<< commandname << " [OPTION]..." << "\n";
cout << desc << "\n";
cout << "Examples:" << "\n";
@@ -1114,13 +1115,16 @@ static void ParseArguments(int argc, char* argv[], globalConfig& conf) {
singlePuzzle = true;
singlePuzzleNr = vm["puzzle-single-level"].as<int>();
}
- if(vm.count("no-auto-scale")) {
+ if (vm.count("no-auto-scale")) {
conf.autoScale = false;
}
if (vm.count("puzzle-level-file")) {
conf.puzzleName = vm["puzzle-level-file"].as<string>();
}
-
+ if (vm.count("play-replay")) {
+ globalData.replayArgument = vm["play-replay"].as<string>();
+ }
+
}
//Warning: the arguments to main must be "int argc, char* argv[]" NO CONST! or SDL_main will fail to find it
@@ -1301,7 +1305,7 @@ int main(int argc, char* argv[]) {
BlockGameSdl theGame2 = BlockGameSdl(globalData.xsize-500, 100);
player1 = &theGame;
player2 = &theGame2;
-
+
BlockGameAction a;
a.action = BlockGameAction::Action::SET_GAME_OVER;
theGame.DoAction(a);
@@ -1327,6 +1331,10 @@ int main(int argc, char* argv[]) {
if (singlePuzzle) {
runGame(Gametype::Puzzle, singlePuzzleNr);
}
+ else if (globalData.replayArgument.length()) {
+ ReplayPlayer rp;
+ RunGameState(rp);
+ }
else {
//game loop
MainMenu();
@@ -1388,7 +1396,6 @@ int main(int argc, char* argv[]) {
return 0;
}
-
int runGame(Gametype gametype, int level) {
globalData.theTopScoresEndless = Highscore("endless");
globalData.theTopScoresTimeTrial = Highscore("timetrial");
@@ -1414,7 +1421,7 @@ int runGame(Gametype gametype, int level) {
theGame2.name = globalData.player2name;
bool mustsetupgame = true;
-
+
if (singlePuzzle) {
LoadPuzzleStages();
BlockGameStartInfo s;
@@ -1437,60 +1444,59 @@ int runGame(Gametype gametype, int level) {
registerTTHighscorePlayer1 = false;
registerTTHighscorePlayer2 = false;
switch (gametype) {
- case Gametype::SinglePlayerTimeTrial:
- StartSinglePlayerTimeTrial();
- break;
- case Gametype::StageClear: {
- int myLevel = PuzzleLevelSelect(1);
- if (myLevel == -1) {
- return 1;
- }
- BlockGameStartInfo s;
- s.ticks = SDL_GetTicks();
- s.stageClear = true;
- s.level = myLevel;
- theGame.NewGame(s);
- DrawBackground(globalData.screen);
- twoPlayers =false;
- BlockGameAction a;
- a.action = BlockGameAction::Action::SET_GAME_OVER;
- theGame2.DoAction(a);
- theGame.name = globalData.player1name;
- theGame2.name = globalData.player2name;
+ case Gametype::SinglePlayerTimeTrial:
+ StartSinglePlayerTimeTrial();
+ break;
+ case Gametype::StageClear: {
+ int myLevel = PuzzleLevelSelect(1);
+ if (myLevel == -1) {
+ return 1;
+ }
+ BlockGameStartInfo s;
+ s.ticks = SDL_GetTicks();
+ s.stageClear = true;
+ s.level = myLevel;
+ theGame.NewGame(s);
+ DrawBackground(globalData.screen);
+ twoPlayers =false;
+ BlockGameAction a;
+ a.action = BlockGameAction::Action::SET_GAME_OVER;
+ theGame2.DoAction(a);
+ theGame.name = globalData.player1name;
+ theGame2.name = globalData.player2name;
+ }
+ break;
+ case Gametype::Puzzle:
+ if (StartSinglePlayerPuzzle()) {
+ return 1;
}
break;
- case Gametype::Puzzle:
- if (StartSinglePlayerPuzzle()) {
- return 1;
- }
- break;
- case Gametype::SinglePlayerVs:
- {
- //1 player - Vs mode
- int theAIlevel = level; //startSingleVs();
- BlockGameStartInfo startInfo;
- startInfo.ticks = SDL_GetTicks();
- startInfo.vsMode = true;
- startInfo.vsAI = true;
- startInfo.level = theAIlevel;
- theGame.NewGame(startInfo);
- startInfo.AI = true;
- theGame2.NewGame(startInfo);
- DrawBackground(globalData.screen);
- twoPlayers = true; //Single player, but AI plays
- theGame.name = globalData.player1name;
- theGame2.name = globalData.player2name;
- }
- break;
- case Gametype::TwoPlayerTimeTrial:
- StarTwoPlayerTimeTrial();
- break;
- case Gametype::TwoPlayerVs:
- StartTwoPlayerVs();
- break;
- case Gametype::SinglePlayerEndless:
- default:
- StartSinglePlayerEndless();
+ case Gametype::SinglePlayerVs: {
+ //1 player - Vs mode
+ int theAIlevel = level; //startSingleVs();
+ BlockGameStartInfo startInfo;
+ startInfo.ticks = SDL_GetTicks();
+ startInfo.vsMode = true;
+ startInfo.vsAI = true;
+ startInfo.level = theAIlevel;
+ theGame.NewGame(startInfo);
+ startInfo.AI = true;
+ theGame2.NewGame(startInfo);
+ DrawBackground(globalData.screen);
+ twoPlayers = true; //Single player, but AI plays
+ theGame.name = globalData.player1name;
+ theGame2.name = globalData.player2name;
+ }
+ break;
+ case Gametype::TwoPlayerTimeTrial:
+ StarTwoPlayerTimeTrial();
+ break;
+ case Gametype::TwoPlayerVs:
+ StartTwoPlayerVs();
+ break;
+ case Gametype::SinglePlayerEndless:
+ default:
+ StartSinglePlayerEndless();
};
mustsetupgame = false;
DrawBackground(globalData.screen);
@@ -1523,7 +1529,7 @@ int runGame(Gametype gametype, int level) {
Config::getInstance()->setShuttingDown(5);
done = 1;
}
-
+
if (theGame.isGameOver() && isEscapeEvent(event)) {
done = 1;
}
@@ -1703,7 +1709,7 @@ int runGame(Gametype gametype, int level) {
}
mouseDownX = event.button.x;
mouseDownY = event.button.y;
- }
+ }
if (event.button.button == SDL_BUTTON_RIGHT) {
bool pressed = false;
int x = 0;
@@ -1768,7 +1774,7 @@ int runGame(Gametype gametype, int level) {
}
}
}
-
+
}
} //while event PollEvent - read keys
@@ -1792,15 +1798,15 @@ int runGame(Gametype gametype, int level) {
if (stageButtonStatus != SBdontShow && (globalData.mousex > theGame.GetTopX()+cordNextButton.x)
&& (globalData.mousex < theGame.GetTopX()+cordNextButton.x+cordNextButton.xsize)
&& (globalData.mousey > theGame.GetTopY()+cordNextButton.y)
- && (globalData.mousey < theGame.GetTopY()+cordNextButton.y+cordNextButton.ysize)) {
+ && (globalData.mousey < theGame.GetTopY()+cordNextButton.y+cordNextButton.ysize)) {
//Clicked the next button after a stage clear or puzzle
nextLevel(theGame, SDL_GetTicks());
}
-
+
if (stageButtonStatus != SBdontShow && (globalData.mousex > theGame.GetTopX()+cordRetryButton .x)
&&(globalData.mousex < theGame.GetTopX()+cordRetryButton.x+cordRetryButton.xsize)
&&(globalData.mousey > theGame.GetTopY()+cordRetryButton.y)
- &&(globalData.mousey < theGame.GetTopY()+cordRetryButton.y+cordRetryButton.ysize)) {
+ &&(globalData.mousey < theGame.GetTopY()+cordRetryButton.y+cordRetryButton.ysize)) {
//Clicked the retry button
retryLevel(theGame, SDL_GetTicks());
}
diff --git a/source/code/replayhandler.cpp b/source/code/replayhandler.cpp
index 657e7f2..e213f35 100644
--- a/source/code/replayhandler.cpp
+++ b/source/code/replayhandler.cpp
@@ -49,6 +49,26 @@ static void SaveReplayToFile(const SavedReplayStruct& sr, const std::string& fil
sago::WriteFileContent(filename.c_str(), ss.str());
}
+static void LoadReplayFromPhysFile(SavedReplayStruct& sr, const std::string& filename) {
+ std::string filecontent = sago::GetFileContent(filename.c_str());
+ std::stringstream ss(filecontent);
+ {
+ cereal::JSONInputArchive archive(ss);
+ archive(cereal::make_nvp("savedReplay", sr));
+ }
+}
+
+void LoadReplay(const std::string& filename, BlockGameInfo& game1, BlockGameInfo& game2) {
+ SavedReplayStruct sr;
+ LoadReplayFromPhysFile(sr, filename);
+ if (sr.playerInfo.size() > 0) {
+ game1 = sr.playerInfo.at(0);
+ }
+ if (sr.playerInfo.size() > 1) {
+ game2 = sr.playerInfo.at(1);
+ }
+}
+
void SaveReplay(const BlockGameInfo& game1) {
SavedReplayStruct sr;
sr.numberOfPlayers = 1;