//======================================================================== // TeapotWars.cpp : source file for the sample game // // Part of the GameCode4 Application // // GameCode4 is the sample application that encapsulates much of the source code // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David // "Rez" Graham, published by Charles River Media. // ISBN-10: 1133776574 | ISBN-13: 978-1133776574 // // If this source code has found it's way to you, and you think it has helped you // in any way, do the authors a favor and buy a new copy of the book - there are // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com // by clicking here: // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller= // // There's a companion web site at http://www.mcshaffry.com/GameCode/ // // The source code is managed and maintained through Google Code: // http://code.google.com/p/gamecode4/ // // (c) Copyright 2012 Michael L. McShaffry and David Graham // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser GPL v3 // as published by the Free Software Foundation. // // 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 // http://www.gnu.org/licenses/lgpl-3.0.txt for more details. // // You should have received a copy of the GNU Lesser GPL v3 // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //======================================================================== #include "Unix/TeapotWarsStd.h" #include "../GCC4/GameCode4/GameCode.h" #include "../GCC4/EventManager/EventManagerImpl.h" #include "../GCC4/Utilities/String.h" #include "Unix/TeapotWars.h" #include "TeapotWarsView.h" #include "TeapotEvents.h" TeapotWarsApp g_TeapotWarsApp; //======================================================================== // wWinMain - Defines the entry point to your application (Chapter 5 - page 121) // // In the book _tWinMain goes straight into the initialization sequence. Here, // the GameCode4() free function handles it. This allows the GameCode4 function // to live in a library, separating the game engine from game specific code, // in this case TeapotWars. // //======================================================================== int main(int argc, char **argv) { return GameCode4(argc, argv); } //======================================================================== // // TeapotWarsApp Implementation - Chapter 21, page 722 // //======================================================================== // // TeapotWarsApp::VCreateGameAndView // BaseGameLogic *TeapotWarsApp::VCreateGameAndView() { m_pGame = GCC_NEW TeapotWarsLogic(); m_pGame->Init(); std::shared_ptr menuView(GCC_NEW MainMenuView()); m_pGame->VAddView(menuView); return m_pGame; } //======================================================================== // // TeapotWarsLogic Implementation - Chapter 21, page 725 // //======================================================================== // // TeapotWarsLogic::TeapotWarsLogic // TeapotWarsLogic::TeapotWarsLogic() { // m_pPhysics.reset(CreateGamePhysics()); RegisterAllDelegates(); } // // TeapotWarsLogic::~TeapotWarsLogic // TeapotWarsLogic::~TeapotWarsLogic() { RemoveAllDelegates(); // DestroyAllNetworkEventForwarders(); } // // TeapotWarsLogic::VChangeState // void TeapotWarsLogic::VChangeState(BaseGameState newState) { BaseGameLogic::VChangeState(newState); switch(newState) { case BGS_WaitingForPlayers: { // spawn all local players (should only be one, though we might support more in the future) GCC_ASSERT(m_ExpectedPlayers == 1); for (int i = 0; i < m_ExpectedPlayers; ++i) { std::shared_ptr playersView(GCC_NEW TeapotWarsHumanView(g_pApp->m_Renderer)); VAddView(playersView); if (m_bProxy) { // if we are a remote player, all we have to do is spawn our view - the server will do the rest. return; } } // // spawn all remote player's views on the game // for (int i = 0; i < m_ExpectedRemotePlayers; ++i) // { // std::shared_ptr remoteGameView(GCC_NEW NetworkGameView); // VAddView(remoteGameView); // } // // spawn all AI's views on the game // for (int i = 0; i < m_ExpectedAI; ++i) // { // std::shared_ptr aiView(GCC_NEW AITeapotView(m_pPathingGraph)); // VAddView(aiView); // } break; } case BGS_SpawningPlayersActors: { if (m_bProxy) { // only the server needs to do this return; } for (auto it = m_gameViews.begin(); it != m_gameViews.end(); ++it) { std::shared_ptr pView = *it; if (pView->VGetType() == GameView_Human) { StrongActorPtr pActor = VCreateActor("actors/player_teapot.xml", NULL); if (pActor) { std::shared_ptr pNewActorEvent(GCC_NEW EvtData_New_Actor(pActor->GetId(), pView->VGetId())); IEventManager::Get()->VTriggerEvent(pNewActorEvent); // [rez] This needs to happen asap because the constructor function for Lua (which is called in through VCreateActor()) queues an event that expects this event to have been handled } } } } } } // // TeapotWarsLogic::VAddView // void TeapotWarsLogic::VAddView(std::shared_ptr pView, ActorId actor) { BaseGameLogic::VAddView(pView, actor); // This is commented out because while the view is created and waiting, the player has NOT attached yet. // if (dynamic_pointer_cast(pView)) // { // m_HumanPlayersAttached++; // } if (dynamic_pointer_cast(pView)) { m_HumanPlayersAttached++; } // else if (dynamic_pointer_cast(pView)) // { // m_AIPlayersAttached++; // } } void TeapotWarsLogic::RegisterAllDelegates(void) { // FUTURE WORK: Lots of these functions are ok to go into the base game logic! IEventManager* pGlobalEventManager = IEventManager::Get(); // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::RemoteClientDelegate), EvtData_Remote_Client::sk_EventType); // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::MoveActorDelegate), EvtData_Move_Actor::sk_EventType); pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::RequestStartGameDelegate), EvtData_Request_Start_Game::sk_EventType); // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::NetworkPlayerActorAssignmentDelegate), EvtData_Network_Player_Actor_Assignment::sk_EventType); pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::EnvironmentLoadedDelegate), EvtData_Environment_Loaded::sk_EventType); // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::EnvironmentLoadedDelegate), EvtData_Remote_Environment_Loaded::sk_EventType); // FUTURE WORK: Only these belong in TeapotWars. // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::StartThrustDelegate), EvtData_StartThrust::sk_EventType); // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::EndThrustDelegate), EvtData_EndThrust::sk_EventType); // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::StartSteerDelegate), EvtData_StartSteer::sk_EventType); // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::EndSteerDelegate), EvtData_EndSteer::sk_EventType); pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsLogic::TestScriptDelegate), EvtData_ScriptEventTest_FromLua::sk_EventType); } void TeapotWarsLogic::RemoveAllDelegates(void) { // FUTURE WORK: See the note in RegisterDelegates above.... IEventManager* pGlobalEventManager = IEventManager::Get(); // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::RemoteClientDelegate), EvtData_Remote_Client::sk_EventType); // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::MoveActorDelegate), EvtData_Move_Actor::sk_EventType); pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::RequestStartGameDelegate), EvtData_Request_Start_Game::sk_EventType); // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::NetworkPlayerActorAssignmentDelegate), EvtData_Network_Player_Actor_Assignment::sk_EventType); pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::EnvironmentLoadedDelegate), EvtData_Environment_Loaded::sk_EventType); // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::EnvironmentLoadedDelegate), EvtData_Remote_Environment_Loaded::sk_EventType); // if (m_bProxy) // { // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::RequestNewActorDelegate), EvtData_Request_New_Actor::sk_EventType); // } // FUTURE WORK: These belong in teapot wars! // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::StartThrustDelegate), EvtData_StartThrust::sk_EventType); // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::EndThrustDelegate), EvtData_EndThrust::sk_EventType); // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::StartSteerDelegate), EvtData_StartSteer::sk_EventType); // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::EndSteerDelegate), EvtData_EndSteer::sk_EventType); pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsLogic::TestScriptDelegate), EvtData_ScriptEventTest_FromLua::sk_EventType); } void TeapotWarsLogic::RequestStartGameDelegate(IEventDataPtr pEventData) { VChangeState(BGS_WaitingForPlayers); } void TeapotWarsLogic::EnvironmentLoadedDelegate(IEventDataPtr pEventData) { ++m_HumanGamesLoaded; } void TeapotWarsLogic::TestScriptDelegate(IEventDataPtr pEventData) { std::shared_ptr pCastEventData = static_pointer_cast(pEventData); GCC_LOG("Lua", "Event received in C++ from Lua: " + ToStr(pCastEventData->GetNum())); } bool TeapotWarsLogic::VLoadGameDelegate(TiXmlElement* pLevelData) { RegisterTeapotScriptEvents(); return true; }