//======================================================================== // 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 "../GCC4/Unix/GameCodeStd.cpp" #include "Unix/TeapotWars.h" #include "../GCC4/EventManager/Events.h" #include "../GCC4/EventManager/EventManagerImpl.h" // #include "../GCC4/Physics/PhysicsEventListener.h" #include "../GCC4/LUAScripting/LuaStateManager.h" // [rez] For debugging only; the view shouldn't use Lua #include "TeapotWarsView.h" #include "TeapotEvents.h" #include #include #include extern TeapotWarsApp g_TeaportWarsApp; //======================================================================== // // MainMenuUI & MainMenuView implementation // // //======================================================================== #define CID_START_BUTTON (0) #define CID_QUIT_BUTTON (1) const int g_SampleUIWidth = 600; const int g_SampleUIHeight = 600; MainMenuUI::MainMenuUI() { m_bCreatingGame = true; m_Levels = g_pApp->GetGameLogic()->GetLevelManager()->GetLevels(); m_LevelIndex = 0; // grab defaults from the game options. m_NumAIs = g_pApp->m_Options.m_numAIs; m_NumPlayers = g_pApp->m_Options.m_expectedPlayers; m_HostName = g_pApp->m_Options.m_gameHost; m_HostListenPort = g_pApp->m_Options.m_listenPort; m_ClientAttachPort = g_pApp->m_Options.m_listenPort; } int MainMenuUI::VOnRestore() { // m_SampleUI.SetLocation( (g_pApp->GetScreenSize().x - g_SampleUIWidth)/2, (g_pApp->GetScreenSize().y - g_SampleUIHeight) / 2 ); // m_SampleUI.SetSize( g_SampleUIWidth, g_SampleUIHeight ); // return S_OK; return 0; } int MainMenuUI::VOnRender(double fTime, float fElapsedTime) { ImGuiIO& io = ImGui::GetIO(); // don't let title bar change colour when clicked ImVec4 titleBgColor = ImGui::GetStyleColorVec4(ImGuiCol_TitleBg); ImGui::PushStyleColor(ImGuiCol_TitleBgActive, titleBgColor); // maths to centre window on screen ImVec2 screenSize = io.DisplaySize; ImVec2 screenCenter = ImVec2(screenSize.x * 0.5f, screenSize.y * 0.5f); ImGui::SetNextWindowPos(screenCenter, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); // Let's draw a menu! ImGui::Begin("Teapot Wars Main Menu", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize ); ImGui::Text("Level"); if (ImGui::BeginCombo("##Level", m_Levels[m_LevelIndex].c_str(), 0)) { for (int i = 0; i < m_Levels.size(); i++) { const bool isSelected = (m_LevelIndex == i); if (ImGui::Selectable(m_Levels[i].c_str(), m_LevelIndex == i)) m_LevelIndex = i; // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) if (isSelected) ImGui::SetItemDefaultFocus(); } ImGui::EndCombo(); } ImGui::Dummy(ImVec2(0.0f, 20.0f)); if (ImGui::RadioButton("Create Game", m_bCreatingGame)) { m_bCreatingGame = true; } ImGui::Text("Number of Players"); ImGui::SliderInt("##Number of Players", &m_NumPlayers, 1, g_pApp->m_Options.m_maxPlayers); ImGui::Dummy(ImVec2(0.0f, 5.0f)); ImGui::Text("Number of AIs"); ImGui::SliderInt("##Number of AIs", &m_NumAIs, 0, g_pApp->m_Options.m_maxAIs); ImGui::Dummy(ImVec2(0.0f, 20.0f)); if (ImGui::RadioButton("Join Game", !m_bCreatingGame)) { m_bCreatingGame = false; } ImGui::Text("Host Attach Port"); ImGui::InputText("##Host Attach Port", &m_HostListenPort); ImGui::Dummy(ImVec2(0.0f, 5.0f)); ImGui::Text("Host Name"); ImGui::InputText("##Host Name", &m_HostName); ImGui::Dummy(ImVec2(0.0f, 20.0f)); if (ImGui::Button("Start Game")) _OnGUIEvent(CID_START_BUTTON); ImGui::SameLine(); if (ImGui::Button("Quit")) _OnGUIEvent(CID_QUIT_BUTTON); ImGui::End(); ImGui::PopStyleColor(); return 0; } int MainMenuUI::VOnMsgProc( SDL_Event &e ) { return 0; } //-------------------------------------------------------------------------------------- // Handles the GUI events //-------------------------------------------------------------------------------------- // Note: pUserContext added to comply with DirectX 9c - June 2005 Update // void MainMenuUI::_OnGUIEvent(unsigned int event) { switch (event) { case CID_START_BUTTON: { g_pApp->m_Options.m_numAIs = m_NumAIs; g_pApp->m_Options.m_expectedPlayers = m_NumPlayers; if (m_bCreatingGame) { if (m_LevelIndex == -1) { // FUTURE WORK - AN ERROR DIALOG WOULD BE GOOD HERE, OR JUST DEFALT THE SELECTION TO SOMETHING VALID return; } g_pApp->m_Options.m_Level = m_Levels[m_LevelIndex]; g_pApp->m_Options.m_gameHost = ""; g_pApp->m_Options.m_listenPort = atoi(m_HostListenPort.c_str()); } else { g_pApp->m_Options.m_gameHost = m_HostName; g_pApp->m_Options.m_listenPort = atoi(m_ClientAttachPort.c_str()); } VSetVisible(false); std::shared_ptr pRequestStartGameEvent(GCC_NEW EvtData_Request_Start_Game()); IEventManager::Get()->VQueueEvent(pRequestStartGameEvent); break; } case CID_QUIT_BUTTON: { break; } } } MainMenuView::MainMenuView() : HumanView(std::shared_ptr()) { // TODO(munnellg) - implement m_MainMenuUI.reset(GCC_NEW MainMenuUI); VPushElement(m_MainMenuUI); } MainMenuView::~MainMenuView() { } void MainMenuView::VRenderText() { HumanView::VRenderText(); } void MainMenuView::VOnUpdate(unsigned long deltaMs) { HumanView::VOnUpdate(deltaMs); } int MainMenuView::VOnMsgProc( SDL_Event &e ) { if (m_MainMenuUI->VIsVisible() ) { if (HumanView::VOnMsgProc(e)) return 1; } return 0; } //======================================================================== // // TeapotWarsHumanView Implementation // //======================================================================== // // TeapotWarsHumanView::TeapotWarsHumanView - Chapter 19, page 724 // TeapotWarsHumanView::TeapotWarsHumanView(std::shared_ptr renderer) : HumanView(renderer) { m_bShowUI = true; RegisterAllDelegates(); } TeapotWarsHumanView::~TeapotWarsHumanView() { RemoveAllDelegates(); } // // TeapotWarsHumanView::VOnMsgProc - Chapter 19, page 727 // int TeapotWarsHumanView::VOnMsgProc( SDL_Event &e ) { if (HumanView::VOnMsgProc(e)) return 1; switch (e.type) { case SDL_EVENT_KEY_DOWN: switch (e.key.scancode) { case SDL_SCANCODE_F4: { Resource resource("scripts/test.lua"); std::shared_ptr pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource); // this actually loads the lua file from the zip file return 1; } case SDL_SCANCODE_F5: { std::shared_ptr pEvent(GCC_NEW EvtData_ScriptEventTest_ToLua); IEventManager::Get()->VQueueEvent(pEvent); return 1; } // case SDL_SCANCODE_F6: // { // LuaStateManager::Get()->VExecuteString("TestProcess()"); // return 1; // } case SDL_SCANCODE_F8: { // m_KeyboardHandler = m_pTeapotController; // m_PointerHandler = m_pTeapotController; m_pCamera->SetTarget(m_pTeapot); // m_pTeapot->SetAlpha(0.8f); SDL_SetWindowRelativeMouseMode(g_pApp->GetWindow(), false); return 1; } case SDL_SCANCODE_F11: { m_KeyboardHandler = m_pFreeCameraController; m_PointerHandler = m_pFreeCameraController; m_pCamera->ClearTarget(); // m_pTeapot->SetAlpha(0.8f); SDL_SetWindowRelativeMouseMode(g_pApp->GetWindow(), true); return 1; } default: break; } default: break; } return 0; } void TeapotWarsHumanView::VRenderText() { // TODO(munnellg) - implement } void TeapotWarsHumanView::VOnUpdate(unsigned long deltaMs) { HumanView::VOnUpdate( deltaMs ); if (m_pFreeCameraController) { m_pFreeCameraController->OnUpdate(deltaMs); } // if (m_pTeapotController) // { // m_pTeapotController->OnUpdate(deltaMs); // } //Send out a tick to listeners // std::shared_ptr pTickEvent(GCC_NEW EvtData_Update_Tick(deltaMs)); // IEventManager::Get()->VTriggerEvent(pTickEvent); } void TeapotWarsHumanView::VOnAttach(GameViewId vid, ActorId aid) { // TODO(munnellg) - implement } bool TeapotWarsHumanView::VLoadGameDelegate(TiXmlElement* pLevelData) { if (!HumanView::VLoadGameDelegate(pLevelData)) return false; // m_StandardHUD.reset(GCC_NEW StandardHUD); // VPushElement(m_StandardHUD); // A movement controller is going to control the camera, // but it could be constructed with any of the objects you see in this // function. You can have your very own remote controlled sphere. What fun... m_pFreeCameraController.reset(GCC_NEW MovementController(m_pCamera, 0, 0, false)); m_pScene->VOnRestore(); return true; } void TeapotWarsHumanView::VSetControlledActor(ActorId actorId) { m_pTeapot = static_pointer_cast(m_pScene->FindActor(actorId)); if (!m_pTeapot) { GCC_ERROR("Invalid teapot"); return; } HumanView::VSetControlledActor(actorId); // m_pTeapotController.reset(GCC_NEW TeapotController(m_pTeapot)); // m_KeyboardHandler = m_pTeapotController; // m_PointerHandler = m_pTeapotController; m_pCamera->SetTarget(m_pTeapot); // m_pTeapot->SetAlpha(0.8f); } void TeapotWarsHumanView::SetControlledActorDelegate(IEventDataPtr pEventData) { std::shared_ptr pCastEventData = static_pointer_cast(pEventData); VSetControlledActor(pCastEventData->GetActorId()); } void TeapotWarsHumanView::RegisterAllDelegates(void) { // TODO(munnellg) - implement // [mrmike] Move, New, and Destroy actor events are now handled by the HumanView, as are the PlaySound and GameState events IEventManager* pGlobalEventManager = IEventManager::Get(); // pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsHumanView::GameplayUiUpdateDelegate), EvtData_Gameplay_UI_Update::sk_EventType); pGlobalEventManager->VAddListener(MakeDelegate(this, &TeapotWarsHumanView::SetControlledActorDelegate), EvtData_Set_Controlled_Actor::sk_EventType); } void TeapotWarsHumanView::RemoveAllDelegates(void) { // TODO(munnellg) - implement IEventManager* pGlobalEventManager = IEventManager::Get(); // pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsHumanView::GameplayUiUpdateDelegate), EvtData_Gameplay_UI_Update::sk_EventType); pGlobalEventManager->VRemoveListener(MakeDelegate(this, &TeapotWarsHumanView::SetControlledActorDelegate), EvtData_Set_Controlled_Actor::sk_EventType); }