From df4c837a8a7fe9bcdb4511ada37910ff0893e7f8 Mon Sep 17 00:00:00 2001 From: ondralukes Date: Mon, 23 Dec 2019 13:15:40 +0000 Subject: [PATCH 1/5] Saving game after every move --- App.cpp | 2 +- Game.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- Game.h | 7 ++++++- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/App.cpp b/App.cpp index f2898c5..bc1dce0 100644 --- a/App.cpp +++ b/App.cpp @@ -23,7 +23,7 @@ App::App() Game *theGame = new Game(4, 4); WindowBoard *win = new WindowBoard(theGame); BMessenger gameMsg(NULL, theGame); - gameMsg.SendMessage(H2048_NEW_GAME); + gameMsg.SendMessage(H2048_LOAD_GAME); } int main() diff --git a/Game.cpp b/Game.cpp index 9b54f69..6439c16 100644 --- a/Game.cpp +++ b/Game.cpp @@ -35,7 +35,10 @@ Game::Game(uint32 sizeX, uint32 sizeY) sprintf(fHighscore_path, "%s/%s", buffer, HAIKU2048_DIRECTORY); result = create_directory(fHighscore_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); sprintf(fHighscore_path, "%s/%s", fHighscore_path, HIGHSCORE_FILENAME); - + + sprintf(fSaveFile_path, "%s/%s", buffer, HAIKU2048_DIRECTORY); + sprintf(fSaveFile_path, "%s/%s", fSaveFile_path, SAVEFILE_FILENAME); + std::ifstream highscore(fHighscore_path, std::ios::binary); memset(fUsername, 0, sizeof(char) * 32); memset(fPlayername, 0, sizeof(char) * 32); @@ -47,7 +50,6 @@ Game::Game(uint32 sizeX, uint32 sizeY) } fBoard = new uint32[fSizeX * fSizeY]; fPreviousBoard = new uint32[fSizeX * fSizeY]; - Run(); } @@ -69,6 +71,12 @@ Game::MessageReceived(BMessage *message) break; case H2048_NEW_GAME: newGame(); + save(); + break; + case H2048_LOAD_GAME: + if(!load()){ + newGame(); + } break; case H2048_NAME_REQUESTED: { @@ -351,7 +359,9 @@ Game::makeMove(GameMove direction) broadcastMessage(request_name); writeHighscore(); } - } + } else { + save(); + } } void @@ -437,4 +447,43 @@ Game::undoMove() { // Now user can't undo anymore changed.AddBool("canUndo", false); broadcastMessage(changed); + save(); } + +void +Game::save(){ + std::ofstream saveFile(fSaveFile_path, std::ios_base::trunc| std::ios_base::binary); + if(saveFile.good()){ + saveFile.write((char*)fBoard,sizeof(uint32_t)*fSizeX*fSizeY); + saveFile.write((char*)fPreviousBoard,sizeof(uint32_t)*fSizeX*fSizeY); + saveFile.write((char*)&fScore,sizeof(uint32_t)); + saveFile.write((char*)&fPreviousScore,sizeof(uint32_t)); + saveFile.write((char*)&fCanUndo,sizeof(bool)); + saveFile.close(); + } + } +bool +Game::load(){ + std::ifstream saveFile(fSaveFile_path, std::ios::binary); + if(saveFile.good()){ + saveFile.read((char*)fBoard,sizeof(uint32_t)*fSizeX*fSizeY); + saveFile.read((char*)fPreviousBoard,sizeof(uint32_t)*fSizeX*fSizeY); + saveFile.read((char*)&fScore,sizeof(uint32_t)); + saveFile.read((char*)&fPreviousScore,sizeof(uint32_t)); + saveFile.read((char*)&fCanUndo,sizeof(bool)); + saveFile.close(); + + BMessage startNotification(H2048_GAME_STARTED); + broadcastMessage(startNotification); + + //Notify the boards about fCanUndo state + BMessage changed(H2048_BOARD_CHANGED); + changed.AddBool("canUndo", fCanUndo); + broadcastMessage(changed); + + fInGame = true; + return true; + } else { + return false; + } + } diff --git a/Game.h b/Game.h index ba19220..76046a6 100644 --- a/Game.h +++ b/Game.h @@ -13,6 +13,7 @@ #define HIGHSCORE_FILENAME "Highscore" #define HAIKU2048_DIRECTORY "Haiku2048" +#define SAVEFILE_FILENAME "Save" class BMessage; class BMessenger; @@ -30,7 +31,8 @@ enum H2048_NEW_GAME = '48NG', H2048_NAME_REQUESTED= '48NR', H2048_UNDO_MOVE = '48UM', - H2048_MAKE_MOVE = '48MM' + H2048_MAKE_MOVE = '48MM', + H2048_LOAD_GAME = '48LG' }; class Game : public BLooper @@ -57,6 +59,8 @@ class Game : public BLooper void undoMove(); void copyBoard(uint32 *from, uint32 *to); void broadcastMessage(BMessage &msg); + void save(); + bool load(); uint32 * boardAt(uint32 x, uint32 y); uint32 newTile(); bool gameOver(); @@ -83,6 +87,7 @@ class Game : public BLooper char fUsername[32]; char fPlayername[32]; char fHighscore_path[128]; + char fSaveFile_path[128]; }; #endif // GAME_H From e733610196917251fc80ee744672ec9cc3545db6 Mon Sep 17 00:00:00 2001 From: ondralukes Date: Mon, 23 Dec 2019 13:22:57 +0000 Subject: [PATCH 2/5] Save game when quitting --- Game.cpp | 9 ++++----- Game.h | 3 ++- WindowBoard.cpp | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Game.cpp b/Game.cpp index 6439c16..597717c 100644 --- a/Game.cpp +++ b/Game.cpp @@ -71,13 +71,15 @@ Game::MessageReceived(BMessage *message) break; case H2048_NEW_GAME: newGame(); - save(); break; case H2048_LOAD_GAME: if(!load()){ newGame(); } break; + case H2048_SAVE_GAME: + save(); + break; case H2048_NAME_REQUESTED: { sprintf(fPlayername, "%s", (const char*)message->FindString("playername")); @@ -359,9 +361,7 @@ Game::makeMove(GameMove direction) broadcastMessage(request_name); writeHighscore(); } - } else { - save(); - } + } } void @@ -447,7 +447,6 @@ Game::undoMove() { // Now user can't undo anymore changed.AddBool("canUndo", false); broadcastMessage(changed); - save(); } void diff --git a/Game.h b/Game.h index 76046a6..d675432 100644 --- a/Game.h +++ b/Game.h @@ -32,7 +32,8 @@ enum H2048_NAME_REQUESTED= '48NR', H2048_UNDO_MOVE = '48UM', H2048_MAKE_MOVE = '48MM', - H2048_LOAD_GAME = '48LG' + H2048_LOAD_GAME = '48LG', + H2048_SAVE_GAME = '48SG' }; class Game : public BLooper diff --git a/WindowBoard.cpp b/WindowBoard.cpp index 0d28625..2b1df5d 100644 --- a/WindowBoard.cpp +++ b/WindowBoard.cpp @@ -105,6 +105,8 @@ GameWindow::~GameWindow() bool GameWindow::QuitRequested() { + BMessenger game(NULL, fMaster->fTarget); + game.SendMessage(H2048_SAVE_GAME); be_app_messenger.SendMessage(B_QUIT_REQUESTED); return true; } From 2cef9dbbb28e516f78c476932b14eafe86b97eae Mon Sep 17 00:00:00 2001 From: ondralukes Date: Mon, 23 Dec 2019 14:46:55 +0000 Subject: [PATCH 3/5] Saving window position/size --- Game.cpp | 23 +++++++++++++++++++++-- Game.h | 2 +- GameBoard.cpp | 7 +++++++ GameBoard.h | 4 +++- WindowBoard.cpp | 24 +++++++++++++++++++++++- WindowBoard.h | 1 + 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/Game.cpp b/Game.cpp index 597717c..8e78c30 100644 --- a/Game.cpp +++ b/Game.cpp @@ -5,6 +5,7 @@ #include "Game.h" #include "GameBoard.h" +#include "WindowBoard.h" #include #include @@ -78,8 +79,12 @@ Game::MessageReceived(BMessage *message) } break; case H2048_SAVE_GAME: - save(); + { + BRect frame; + message->FindRect("frame",&frame); + save(frame); break; + } case H2048_NAME_REQUESTED: { sprintf(fPlayername, "%s", (const char*)message->FindString("playername")); @@ -450,14 +455,18 @@ Game::undoMove() { } void -Game::save(){ +Game::save(BRect frame){ std::ofstream saveFile(fSaveFile_path, std::ios_base::trunc| std::ios_base::binary); if(saveFile.good()){ saveFile.write((char*)fBoard,sizeof(uint32_t)*fSizeX*fSizeY); saveFile.write((char*)fPreviousBoard,sizeof(uint32_t)*fSizeX*fSizeY); + saveFile.write((char*)&fScore,sizeof(uint32_t)); saveFile.write((char*)&fPreviousScore,sizeof(uint32_t)); + saveFile.write((char*)&fCanUndo,sizeof(bool)); + + saveFile.write((char*)&frame,sizeof(BRect)); saveFile.close(); } } @@ -467,11 +476,21 @@ Game::load(){ if(saveFile.good()){ saveFile.read((char*)fBoard,sizeof(uint32_t)*fSizeX*fSizeY); saveFile.read((char*)fPreviousBoard,sizeof(uint32_t)*fSizeX*fSizeY); + saveFile.read((char*)&fScore,sizeof(uint32_t)); saveFile.read((char*)&fPreviousScore,sizeof(uint32_t)); + saveFile.read((char*)&fCanUndo,sizeof(bool)); + + BRect frame; + saveFile.read((char*)&frame,sizeof(BRect)); + saveFile.close(); + BMessage setFrameMessage(H2048_SET_FRAME); + setFrameMessage.AddRect("frame",frame); + broadcastMessage(setFrameMessage); + BMessage startNotification(H2048_GAME_STARTED); broadcastMessage(startNotification); diff --git a/Game.h b/Game.h index d675432..fe21260 100644 --- a/Game.h +++ b/Game.h @@ -60,7 +60,7 @@ class Game : public BLooper void undoMove(); void copyBoard(uint32 *from, uint32 *to); void broadcastMessage(BMessage &msg); - void save(); + void save(BRect frame); bool load(); uint32 * boardAt(uint32 x, uint32 y); uint32 newTile(); diff --git a/GameBoard.cpp b/GameBoard.cpp index d0a80f2..a6b7b7f 100644 --- a/GameBoard.cpp +++ b/GameBoard.cpp @@ -39,6 +39,13 @@ GameBoard::MessageReceived(BMessage *message) boardChanged(canUndo); break; + case H2048_SET_FRAME: + { + BRect frame; + message->FindRect("frame", &frame); + setFrame(frame); + break; + } case H2048_REQUEST_NAME: nameRequest(); default: diff --git a/GameBoard.h b/GameBoard.h index ff4c517..17559e3 100644 --- a/GameBoard.h +++ b/GameBoard.h @@ -17,7 +17,8 @@ enum H2048_GAME_STARTED = '48GS', H2048_GAME_ENDED = '48GE', H2048_REQUEST_NAME = '48RN', - H2048_BOARD_CHANGED = '48BC' + H2048_BOARD_CHANGED = '48BC', + H2048_SET_FRAME = '48SB' }; class GameBoard : public BLooper @@ -33,6 +34,7 @@ class GameBoard : public BLooper virtual void gameEnded() = 0; virtual void nameRequest() = 0; virtual void boardChanged(bool canUndo) = 0; + virtual void setFrame(BRect frame) = 0; protected: Game * fTarget; diff --git a/WindowBoard.cpp b/WindowBoard.cpp index 2b1df5d..3e2a0c4 100644 --- a/WindowBoard.cpp +++ b/WindowBoard.cpp @@ -106,7 +106,9 @@ bool GameWindow::QuitRequested() { BMessenger game(NULL, fMaster->fTarget); - game.SendMessage(H2048_SAVE_GAME); + BMessage saveMessage(H2048_SAVE_GAME); + saveMessage.AddRect("frame",Frame()); + game.SendMessage(&saveMessage); be_app_messenger.SendMessage(B_QUIT_REQUESTED); return true; } @@ -129,6 +131,16 @@ GameWindow::MessageReceived(BMessage *message) showBoard(canUndo); break; } + case H2048_SET_FRAME: + { + BRect frame; + message->FindRect("frame",&frame); + MoveTo(frame.LeftTop()); + prevWidth = (int)frame.Width(); + prevHeight = (int)frame.Height(); + ResizeTo((int)frame.Width(),(int)frame.Height()); + break; + } case H2048_UNDO_MOVE: { if (!fMaster->fSending) { @@ -317,3 +329,13 @@ WindowBoard::nameRequest() BMessenger messenger(NULL, fWindow); messenger.SendMessage(H2048_REQUEST_NAME); } + +void +WindowBoard::setFrame(BRect frame) +{ + BMessage setFrame(H2048_SET_FRAME); + setFrame.AddRect("frame", frame); + + BMessenger messenger(NULL, fWindow); + messenger.SendMessage(&setFrame); +} diff --git a/WindowBoard.h b/WindowBoard.h index 52b3171..b08c180 100644 --- a/WindowBoard.h +++ b/WindowBoard.h @@ -76,6 +76,7 @@ friend class GameWindow; void gameEnded(); void nameRequest(); void boardChanged(bool canUndo); + void setFrame(BRect frame); private: bool fSending; From faa963023c73ae636434548c2b53de76e337aef0 Mon Sep 17 00:00:00 2001 From: ondralukes Date: Mon, 23 Dec 2019 19:37:44 +0000 Subject: [PATCH 4/5] Using BMessage and BFile instead of ofstream and ifstream --- Game.cpp | 77 +++++++++++++++++++++++++++++++------------------------- Game.h | 3 ++- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/Game.cpp b/Game.cpp index 8e78c30..74a002e 100644 --- a/Game.cpp +++ b/Game.cpp @@ -456,52 +456,61 @@ Game::undoMove() { void Game::save(BRect frame){ - std::ofstream saveFile(fSaveFile_path, std::ios_base::trunc| std::ios_base::binary); - if(saveFile.good()){ - saveFile.write((char*)fBoard,sizeof(uint32_t)*fSizeX*fSizeY); - saveFile.write((char*)fPreviousBoard,sizeof(uint32_t)*fSizeX*fSizeY); + BFile saveFile(fSaveFile_path,B_WRITE_ONLY | B_CREATE_FILE); - saveFile.write((char*)&fScore,sizeof(uint32_t)); - saveFile.write((char*)&fPreviousScore,sizeof(uint32_t)); + BMessage saveMessage(H2048_SAVE_MESSAGE); - saveFile.write((char*)&fCanUndo,sizeof(bool)); + saveMessage.AddData("board",B_INT32_TYPE,fBoard,sizeof(uint32_t)*fSizeX*fSizeY,false); + saveMessage.AddData("previousBoard",B_INT32_TYPE,fPreviousBoard,sizeof(uint32_t)*fSizeX*fSizeY); - saveFile.write((char*)&frame,sizeof(BRect)); - saveFile.close(); - } + saveMessage.AddUInt32("score",fScore); + saveMessage.AddUInt32("previousScore",fPreviousScore); + + saveMessage.AddBool("canUndo",fCanUndo); + saveMessage.AddRect("windowFrame",frame); + + status_t result = saveMessage.Flatten(&saveFile); } bool Game::load(){ - std::ifstream saveFile(fSaveFile_path, std::ios::binary); - if(saveFile.good()){ - saveFile.read((char*)fBoard,sizeof(uint32_t)*fSizeX*fSizeY); - saveFile.read((char*)fPreviousBoard,sizeof(uint32_t)*fSizeX*fSizeY); + BFile saveFile(fSaveFile_path,B_READ_ONLY); + + BMessage saveMessage(H2048_SAVE_MESSAGE); + status_t result = saveMessage.Unflatten(&saveFile); + if(result!= B_OK){ + return false; + } - saveFile.read((char*)&fScore,sizeof(uint32_t)); - saveFile.read((char*)&fPreviousScore,sizeof(uint32_t)); + bool loadOK = true; + const void * tempPtr; - saveFile.read((char*)&fCanUndo,sizeof(bool)); + loadOK = loadOK && saveMessage.FindData("board",B_ANY_TYPE,0,&tempPtr,NULL) == B_OK; + memcpy(fBoard,tempPtr,sizeof(uint32_t)*fSizeX*fSizeY); - BRect frame; - saveFile.read((char*)&frame,sizeof(BRect)); + loadOK = loadOK && saveMessage.FindData("previousBoard",B_ANY_TYPE,0,&tempPtr,NULL) == B_OK; + memcpy(fPreviousBoard,tempPtr,sizeof(uint32_t)*fSizeX*fSizeY); - saveFile.close(); + loadOK = loadOK && saveMessage.FindUInt32("score",&fScore) == B_OK; + loadOK = loadOK && saveMessage.FindUInt32("previousScore",&fPreviousScore) == B_OK; + loadOK = loadOK && saveMessage.FindBool("canUndo",&fCanUndo) == B_OK; - BMessage setFrameMessage(H2048_SET_FRAME); - setFrameMessage.AddRect("frame",frame); - broadcastMessage(setFrameMessage); + BRect frame; + loadOK = loadOK && saveMessage.FindRect("windowFrame",&frame) == B_OK; - BMessage startNotification(H2048_GAME_STARTED); - broadcastMessage(startNotification); + if(!loadOK) return false; - //Notify the boards about fCanUndo state - BMessage changed(H2048_BOARD_CHANGED); - changed.AddBool("canUndo", fCanUndo); - broadcastMessage(changed); + BMessage setFrameMessage(H2048_SET_FRAME); + setFrameMessage.AddRect("frame",frame); + broadcastMessage(setFrameMessage); - fInGame = true; - return true; - } else { - return false; - } + BMessage startNotification(H2048_GAME_STARTED); + broadcastMessage(startNotification); + + //Notify the boards about fCanUndo state + BMessage changed(H2048_BOARD_CHANGED); + changed.AddBool("canUndo", fCanUndo); + broadcastMessage(changed); + + fInGame = true; + return true; } diff --git a/Game.h b/Game.h index fe21260..7f499be 100644 --- a/Game.h +++ b/Game.h @@ -33,7 +33,8 @@ enum H2048_UNDO_MOVE = '48UM', H2048_MAKE_MOVE = '48MM', H2048_LOAD_GAME = '48LG', - H2048_SAVE_GAME = '48SG' + H2048_SAVE_GAME = '48SG', + H2048_SAVE_MESSAGE = '48SM' }; class Game : public BLooper From da5df36477e5b5976c06b2cb015f8c98fe756f04 Mon Sep 17 00:00:00 2001 From: ondralukes Date: Tue, 24 Dec 2019 09:21:55 +0000 Subject: [PATCH 5/5] Using AddUInt32/FindUInt32 instead of AddData/FindData --- Game.cpp | 20 ++++++++++---------- Game.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Game.cpp b/Game.cpp index 74a002e..f715cf8 100644 --- a/Game.cpp +++ b/Game.cpp @@ -454,14 +454,16 @@ Game::undoMove() { broadcastMessage(changed); } -void +status_t Game::save(BRect frame){ BFile saveFile(fSaveFile_path,B_WRITE_ONLY | B_CREATE_FILE); BMessage saveMessage(H2048_SAVE_MESSAGE); - saveMessage.AddData("board",B_INT32_TYPE,fBoard,sizeof(uint32_t)*fSizeX*fSizeY,false); - saveMessage.AddData("previousBoard",B_INT32_TYPE,fPreviousBoard,sizeof(uint32_t)*fSizeX*fSizeY); + for(int i =0;i