1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Implemented "main menu" in-game option.

This commit is contained in:
Frank Zago 2009-11-01 01:15:16 +00:00
parent c78d48473b
commit 6b5feb63e6
11 changed files with 160 additions and 97 deletions

View File

@ -72,6 +72,7 @@ public:
int playerID, serialID;
std::string dllName;
virtual ~CGameInterface() {};
virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
virtual void garrisonChanged(const CGObjectInstance * obj){};
virtual void heroArtifactSetChanged(const CGHeroInstance*hero){};

View File

@ -1667,7 +1667,7 @@ void CAdvMapInt::deactivate()
townList.deactivate();
terrain.deactivate();
if(std::find(GH.timeinterested.begin(),GH.timeinterested.end(),&infoBar)!=GH.timeinterested.end())
GH.timeinterested.erase(std::find(GH.timeinterested.begin(),GH.timeinterested.end(),&infoBar));
infoBar.deactivate();
infoBar.mode=-1;
LOCPLINT->cingconsole->deactivate();

View File

@ -61,7 +61,7 @@
std::string NAME_AFFIX = "client";
std::string NAME = NAME_VER + std::string(" (") + NAME_AFFIX + ')'; //application name
CGuiHandler GH;
CClient *client = NULL;
static CClient *client;
SDL_Surface *screen = NULL, //main screen surface
*screen2 = NULL,//and hlp surface (used to store not-active interfaces layer)
*screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
@ -79,8 +79,7 @@ void processCommand(const std::string &message);
static void setScreenRes(int w, int h, int bpp, bool fullscreen);
void dispose();
void playIntro();
void listenForEvents();
void startGame(StartInfo * options);
static void listenForEvents();
void init()
{
@ -209,8 +208,9 @@ int main(int argc, char** argv)
loading.join();
tlog0<<"Initialization of VCMI (together): "<<total.getDif()<<std::endl;
new CGPreGame; //will set CGP pointer to itself
CGI->musich->playMusic(musicBase::mainMenu, -1);
new CGPreGame; //will set CGP pointer to itself
hhh = new boost::thread(&CGPreGame::run, CGP);
listenForEvents();
@ -284,9 +284,10 @@ void processCommand(const std::string &message)
//}
else if(cn=="load")
{
// TODO: this code should end the running game and manage to call startGame instead
std::string fname;
readed >> fname;
client->load(fname);
client->loadGame(fname);
}
//else if(cn=="ln")
//{
@ -433,29 +434,26 @@ static void setScreenRes(int w, int h, int bpp, bool fullscreen)
screenBuf = bufOnScreen ? screen : screen2;
}
void listenForEvents()
static void listenForEvents()
{
SDL_Event *ev = NULL;
while(1) //main SDL events loop
{
ev = new SDL_Event();
SDL_Event *ev = new SDL_Event();
//tlog0 << "Waiting... ";
int ret = SDL_WaitEvent(ev);
//tlog0 << "got " << (int)ev->type;
if(ret == 0 || (ev->type==SDL_QUIT) || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
if (ret == 0 || (ev->type==SDL_QUIT) ||
(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
{
if(LOCPLINT)
LOCPLINT->pim->lock();
if (client)
client->close();
client->stop();
if (hhh) {
CGP->terminate = true;
hhh->join();
delete hhh;
hhh = NULL;
}
console->end();
delete console;
console = NULL;
SDL_Delay(750);
@ -470,6 +468,8 @@ void listenForEvents()
bool full = !(screen->flags&SDL_FULLSCREEN);
setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full);
GH.totalRedraw();
delete ev;
continue;
}
else if(ev->type == SDL_USEREVENT && ev->user.code == 1)
{
@ -477,6 +477,12 @@ void listenForEvents()
delete ev;
continue;
}
else if (ev->type == SDL_USEREVENT && ev->user.code == 2) {
client->stop();
delete ev;
continue;
}
//tlog0 << " pushing ";
eventsM.lock();
events.push(ev);
@ -507,47 +513,19 @@ void startGame(StartInfo * options)
CClient cl;
if(options->mode == 0) //new game
{
timeHandler pomtime;
char portc[10];
SDL_itoa(conf.cc.port,portc,10);
CClient::runServer(portc);
tlog0<<"Preparing shared memory and starting server: "<<pomtime.getDif()<<std::endl;
pomtime.getDif();//reset timers
CConnection *c=NULL;
//wait until server is ready
tlog0<<"Waiting for server... ";
cl.waitForServer();
tlog0 << pomtime.getDif()<<std::endl;
while(!c)
{
try
{
tlog0 << "Establishing connection...\n";
c = new CConnection(conf.cc.server,portc,NAME);
}
catch(...)
{
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <<std::endl;
SDL_Delay(2000);
}
}
THC tlog0<<"\tConnecting to the server: "<<pomtime.getDif()<<std::endl;
cl.newGame(c,options);
client = &cl;
CGI->musich->stopMusic();
client->run();
//boost::thread t(boost::bind(&CClient::run,&cl));
cl.newGame(NULL, options);
}
else //load game
{
std::string fname = options->mapname;
boost::algorithm::erase_last(fname,".vlgm1");
cl.load(fname);
client = &cl;
CGI->musich->stopMusic();
client->run();
//boost::thread t(boost::bind(&CClient::run,&cl));
cl.loadGame(fname);
}
client = &cl;
CGI->musich->stopMusic();
client->run();
LOCPLINT->terminate_cond.waitUntil(true);
client->endGame();
client = NULL;
}

View File

@ -100,6 +100,8 @@ CPlayerInterface::CPlayerInterface(int Player, int serial)
SDL_setFramerate(mainFPSmng, 48);
//framerate keeper initialized
cingconsole = new CInGameConsole;
terminate = false;
terminate_cond.set(false);
}
CPlayerInterface::~CPlayerInterface()
{
@ -116,6 +118,8 @@ CPlayerInterface::~CPlayerInterface()
for(std::map<int,SDL_Surface*>::iterator i=graphics->townWins.begin(); i!= graphics->townWins.end(); i++)
SDL_FreeSurface(i->second);
graphics->townWins.clear();
LOCPLINT = NULL;
}
void CPlayerInterface::init(ICallback * CB)
{
@ -179,6 +183,9 @@ void CPlayerInterface::yourTurn()
while(makingTurn) // main loop
{
if (terminate)
break;
pim->lock();
//if there are any waiting dialogs, show them
@ -208,7 +215,10 @@ void CPlayerInterface::yourTurn()
GH.popInt(adventureInt);
cb->endTurn();
} HANDLE_EXCEPTION
} HANDLE_EXCEPTION;
if (terminate)
terminate_cond.set(true);
}
inline void subRect(const int & x, const int & y, const int & z, const SDL_Rect & r, const int & hid)

View File

@ -2,6 +2,7 @@
#define __CPLAYERINTERFACE_H__
#include "../global.h"
#include "../CGameInterface.h"
#include "../lib/CondSh.h"
#include "SDL_framerate.h"
#include <map>
#include <list>
@ -204,6 +205,9 @@ public:
CPlayerInterface(int Player, int serial);//c-tor
~CPlayerInterface();//d-tor
bool terminate; // tell to terminate
CondSh<bool> terminate_cond; // confirm termination
//////////////////////////////////////////////////////////////////////////
template <typename Handler> void serializeTempl(Handler &h, const int version);

View File

@ -44,13 +44,18 @@ using boost::ref;
void startGame(StartInfo * options);
CGPreGame * CGP;
static const CMapHeader *curMap = NULL;
static StartInfo *curOpts = NULL;
static const CMapHeader *curMap;
static StartInfo *curOpts;
static int playerColor, playerSerial;
static std::string selectedName; //set when game is started/loaded
extern void do_quit();
static void do_quit()
{
SDL_Event event;
event.quit.type = SDL_QUIT;
SDL_PushEvent(&event);
}
CMenuScreen::CMenuScreen( EState which )
{
@ -126,15 +131,15 @@ void CGPreGame::run()
CGI->videoh->open("ACREDIT.SMK", true, false);
#endif
GH.pushInt(scrs[mainMenu]);
while(!terminate)
{
if (GH.listInt.size() == 0)
GH.pushInt(scrs[mainMenu]);
CGI->curh->draw1();
SDL_Flip(screen);
CGI->curh->draw2();
SDL_Delay(20); //give time for other apps
GH.topInt()->show(screen);
GH.updateTime();
GH.handleEvents();
@ -362,12 +367,11 @@ void CSelectionScreen::startGame()
selectedName = sInfo.mapname;
StartInfo *si = new StartInfo(sInfo);
GH.popIntTotally(this);
GH.popIntTotally(GH.topInt());
GH.popInt(this);
GH.popInt(GH.topInt());
curMap = NULL;
curOpts = NULL;
::startGame(si);
delete si; //rather won't be called...
}
else
{
@ -376,7 +380,7 @@ void CSelectionScreen::startGame()
selectedName = GVCMIDirs.UserPath + "/Games/" + sel->txt->text + ".vlgm1";
LOCPLINT->cb->save(sel->txt->text);
GH.popIntTotally(this);
GH.popInt(this);
}
}

View File

@ -20,6 +20,7 @@
#include "../mapHandler.h"
#include "CConfigHandler.h"
#include "Client.h"
#include "GUIBase.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
@ -88,7 +89,7 @@ void CClient::init()
serv = NULL;
gs = NULL;
cb = NULL;
must_close = false;
terminate = false;
try
{
shared = new SharedMem();
@ -129,10 +130,8 @@ void CClient::run()
CPack *pack;
while(1)
{
if (must_close) {
serv->close();
tlog3 << "Our socket has been closed.\n";
return;
if (terminate) {
break;
}
//get the package from the server
@ -143,6 +142,11 @@ void CClient::run()
tlog5 << "\treceived server message of type " << typeid(*pack).name() << std::endl;
}
if (terminate) {
delete pack;
break;
}
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
if(apply)
{
@ -163,16 +167,12 @@ void CClient::run()
} HANDLE_EXCEPTION(tlog1 << "Lost connection to server, ending listening thread!\n");
}
void CClient::close()
void CClient::stop()
{
if(!serv)
return;
tlog3 << "Connection has been requested to be closed.\n";
boost::unique_lock<boost::mutex>(*serv->wmx);
*serv << &CloseServer();
tlog3 << "Sent closing signal to the server\n";
must_close = true;
// Game is ending
// Tell the network thread and interface thread to reach a stable state
terminate = true;
LOCPLINT->terminate = true;
}
void CClient::save(const std::string & fname)
@ -186,29 +186,45 @@ void CClient::save(const std::string & fname)
*serv << &SaveGame(fname);
}
void CClient::load( const std::string & fname )
void CClient::endGame()
{
tlog0 <<"\n\nLoading procedure started!\n\n";
timeHandler tmh;
close(); //kill server
tlog0 <<"Sent kill signal to the server: "<<tmh.getDif()<<std::endl;
tlog0 << "\n\nEnding current game!" << std::endl;
delete CGI->mh;
CGI->mh = NULL;
delete CGI->state;
VLC->clear(); //delete old handlers
CGI->state = NULL;
for(std::map<ui8,CGameInterface *>::iterator i = playerint.begin(); i!=playerint.end(); i++)
while (!playerint.empty())
{
delete i->second; //delete player interfaces
delete playerint.begin()->second;
playerint.erase(playerint.begin());
}
BOOST_FOREACH(CCallback *cb, callbacks)
{
delete cb;
}
tlog0 <<"Deleting old data: "<<tmh.getDif()<<std::endl;
if (serv) {
tlog3 << "Connection has been requested to be closed.\n";
boost::unique_lock<boost::mutex>(*serv->wmx);
*serv << &CloseServer();
tlog3 << "Sent closing signal to the server\n";
serv->close();
delete serv;
serv = NULL;
tlog3 << "Our socket has been closed." << std::endl;
}
}
void CClient::loadGame( const std::string & fname )
{
tlog0 <<"\n\nLoading procedure started!\n\n";
timeHandler tmh;
char portc[10];
SDL_itoa(conf.cc.port,portc,10);
@ -300,6 +316,35 @@ int CClient::getSelectedHero()
void CClient::newGame( CConnection *con, StartInfo *si )
{
if (con == NULL) {
timeHandler pomtime;
char portc[10];
SDL_itoa(conf.cc.port,portc,10);
CClient::runServer(portc);
tlog0<<"Preparing shared memory and starting server: "<<pomtime.getDif()<<std::endl;
pomtime.getDif();//reset timers
//wait until server is ready
tlog0<<"Waiting for server... ";
waitForServer();
tlog0 << pomtime.getDif()<<std::endl;
while(!con)
{
try
{
tlog0 << "Establishing connection...\n";
con = new CConnection(conf.cc.server,portc,NAME);
}
catch(...)
{
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" <<std::endl;
SDL_Delay(2000);
}
}
THC tlog0<<"\tConnecting to the server: "<<pomtime.getDif()<<std::endl;
}
timeHandler tmh;
CGI->state = new CGameState();
tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;

View File

@ -61,7 +61,6 @@ public:
std::set<CCallback*> callbacks; //callbacks given to player interfaces
std::map<ui8,CGameInterface *> playerint;
CConnection *serv;
bool must_close;
SharedMem *shared;
BattleAction *curbaction;
CPathsInfo *pathInfo;
@ -75,11 +74,15 @@ public:
~CClient(void);
void init();
void close();
void newGame(CConnection *con, StartInfo *si); //con - connection to server
void endGame();
void save(const std::string & fname);
void load(const std::string & fname);
void loadGame(const std::string & fname);
void run();
void stop();
bool terminate; // tell to terminate
//////////////////////////////////////////////////////////////////////////
//from IGameCallback
int getCurrentPlayer();

View File

@ -521,13 +521,15 @@ void CIntObject::deactivate()
deactivateMouseMove();
if(used & KEYBOARD)
deactivateKeys();
if(used & TIME)
if(active & TIME) // TIME is special
deactivateTimer();
if(used & WHEEL)
deactivateWheel();
if(used & DOUBLECLICK)
deactivateDClick();
assert(!active);
if(defActions & DEACTIVATE)
for(size_t i = 0; i < children.size(); i++)
if(children[i]->recActions & DEACTIVATE)
@ -768,4 +770,4 @@ bool isNumKey( SDLKey key, bool number )
bool isArrowKey( SDLKey key )
{
return key >= SDLK_UP && key <= SDLK_LEFT;
}
}

View File

@ -2840,13 +2840,15 @@ CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface
CSDL_Ext::printAt(CGI->generaltexth->allTexts[577], 283, 217, GEOR16, zwykly, background); //spell book animation
//setting up buttons
save = new AdventureMapButton (CGI->generaltexth->zelp[321].first, CGI->generaltexth->zelp[321].second, boost::bind(&CSystemOptionsWindow::bsavef, this), pos.x+357, pos.y+297, "SOSAVE.DEF", SDLK_s);
save = new AdventureMapButton (CGI->generaltexth->zelp[322].first, CGI->generaltexth->zelp[322].second, boost::bind(&CSystemOptionsWindow::bsavef, this), pos.x+357, pos.y+297, "SOSAVE.DEF", SDLK_s);
std::swap(save->imgs[0][0], save->imgs[0][1]);
quitGame = new AdventureMapButton (CGI->generaltexth->zelp[324].first, CGI->generaltexth->zelp[324].second, boost::bind(&CSystemOptionsWindow::bquitf, this), pos.x+246, pos.y+414, "soquit.def", SDLK_q);
std::swap(quitGame->imgs[0][0], quitGame->imgs[0][1]);
backToMap = new AdventureMapButton (CGI->generaltexth->zelp[325].first, CGI->generaltexth->zelp[325].second, boost::bind(&CSystemOptionsWindow::breturnf, this), pos.x+357, pos.y+414, "soretrn.def", SDLK_RETURN);
mainMenu = new AdventureMapButton (CGI->generaltexth->zelp[320].first, CGI->generaltexth->zelp[320].second, boost::bind(&CSystemOptionsWindow::bmainmenuf, this), pos.x+357, pos.y+357, "SOMAIN.DEF", SDLK_RETURN);
backToMap->assignedKeys.insert(SDLK_ESCAPE);
std::swap(backToMap->imgs[0][0], backToMap->imgs[0][1]);
std::swap(mainMenu->imgs[0][0], mainMenu->imgs[0][1]);
heroMoveSpeed = new CHighlightableButtonsGroup(0);
heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[349].second),CGI->generaltexth->zelp[349].second, "sysopb1.def", pos.x+28, pos.y+77, 1);
@ -2887,22 +2889,26 @@ CSystemOptionsWindow::~CSystemOptionsWindow()
delete save;
delete quitGame;
delete backToMap;
delete mainMenu;
delete heroMoveSpeed;
delete mapScrollSpeed;
delete musicVolume;
delete effectsVolume;
}
void do_quit()
void CSystemOptionsWindow::pushSDLEvent(int type, int usercode)
{
GH.popIntTotally(this);
SDL_Event event;
event.quit.type = SDL_QUIT;
event.type = type;
event.user.code = usercode; // not necessarily used
SDL_PushEvent(&event);
}
void CSystemOptionsWindow::bquitf()
{
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[578], std::vector<SComponent*>(), do_quit, 0, false);
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[578], std::vector<SComponent*>(), boost::bind(&CSystemOptionsWindow::pushSDLEvent, this, SDL_QUIT, 0), 0, false);
}
void CSystemOptionsWindow::breturnf()
@ -2910,6 +2916,10 @@ void CSystemOptionsWindow::breturnf()
GH.popIntTotally(this);
}
void CSystemOptionsWindow::bmainmenuf()
{
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[578], std::vector<SComponent*>(), boost::bind(&CSystemOptionsWindow::pushSDLEvent, this, SDL_USEREVENT, 2), 0, false);
}
void CSystemOptionsWindow::bsavef()
{
@ -2929,6 +2939,7 @@ void CSystemOptionsWindow::activate()
save->activate();
quitGame->activate();
backToMap->activate();
mainMenu->activate();
heroMoveSpeed->activate();
mapScrollSpeed->activate();
musicVolume->activate();
@ -2940,6 +2951,7 @@ void CSystemOptionsWindow::deactivate()
save->deactivate();
quitGame->deactivate();
backToMap->deactivate();
mainMenu->deactivate();
heroMoveSpeed->deactivate();
mapScrollSpeed->deactivate();
musicVolume->deactivate();
@ -2953,6 +2965,7 @@ void CSystemOptionsWindow::show(SDL_Surface *to)
save->show(to);
quitGame->show(to);
backToMap->show(to);
mainMenu->show(to);
heroMoveSpeed->show(to);
mapScrollSpeed->show(to);
musicVolume->show(to);

View File

@ -503,7 +503,7 @@ class CSystemOptionsWindow : public CIntObject
{
private:
SDL_Surface * background; //background of window
AdventureMapButton *load, *save, *restart, *mainMenu, * quitGame, * backToMap; //load, restart and main menu are not used yet
AdventureMapButton *load, *save, *restart, *mainMenu, *quitGame, *backToMap; //load and restart are not used yet
CHighlightableButtonsGroup * heroMoveSpeed;
CHighlightableButtonsGroup * mapScrollSpeed;
CHighlightableButtonsGroup * musicVolume, * effectsVolume;
@ -515,6 +515,9 @@ public:
void bsavef(); //save game
void bquitf(); //quit game
void breturnf(); //return to game
void bmainmenuf(); //return to main menu
void pushSDLEvent(int type, int usercode);
void activate();
void deactivate();