Avoid running the old simulation code in the background when it's not needed.

Optimise GUI updates to only occur when necessary.
Switch to more peaceful music after starting the game.

This was SVN commit r7492.
This commit is contained in:
Ykkrosh 2010-05-01 16:20:58 +00:00
parent 49574953b8
commit e140aa7baf
20 changed files with 229 additions and 101 deletions

View File

@ -34,6 +34,10 @@ function init()
function reallyStartGame()
{
// Stop the music
if (curr_music)
curr_music.fade(-1, 0.0, 5.0); // fade to 0 over 5 seconds
// This is a reserved function name that is executed by the engine when it is ready
// to start the game (ie loading progress has reached 100%).

View File

@ -3,7 +3,6 @@
<include>common/setup.xml</include>
<include>common/styles.xml</include>
<include>common/sprite1.xml</include>
<include>common/init.xml</include>
<include>common/icon_sprites.xml</include>
<include>session_new/sprites.xml</include>
<include>session_new/styles.xml</include>

View File

@ -0,0 +1,27 @@
var g_CurrentMusic = null;
/*
* At some point, this ought to be extended to do dynamic music selection and
* crossfading - it at least needs to pick the music track based on the player's
* civ and peace/battle
*/
function startMusic()
{
var gain = 0.5;
g_CurrentMusic = new Sound("audio/music/germanic_peace_1.ogg");
if (g_CurrentMusic)
{
g_CurrentMusic.loop();
g_CurrentMusic.fade(0.0, gain, 10.0);
}
}
function stopMusic()
{
if (g_CurrentMusic)
{
g_CurrentMusic.fade(-1, 0.0, 5.0);
g_CurrentMusic = null;
}
}

View File

@ -4,19 +4,25 @@ var g_InactiveSelectionColour = { r:1, g:1, b:1, a:0 };
function _setHighlight(ents, colour)
{
Engine.GuiInterfaceCall("SetSelectionHighlight", { "entities":ents, "colour":colour });
if (ents.length)
Engine.GuiInterfaceCall("SetSelectionHighlight", { "entities":ents, "colour":colour });
}
function _setMotionOverlay(ents, enabled)
{
Engine.GuiInterfaceCall("SetMotionDebugOverlay", { "entities":ents, "enabled":enabled });
if (ents.length)
Engine.GuiInterfaceCall("SetMotionDebugOverlay", { "entities":ents, "enabled":enabled });
}
function EntitySelection()
{
// Private properties:
this.selected = {}; // { id: 1, id: 1, ... } for each selected entity ID 'id'
this.highlighted = {}; // { id: 1, ... } for mouseover-highlighted entity IDs
this.motionDebugOverlay = false;
// Public properties:
this.dirty = false; // set whenever the selection has changed
}
EntitySelection.prototype.toggle = function(ent)
@ -33,6 +39,7 @@ EntitySelection.prototype.toggle = function(ent)
_setMotionOverlay([ent], this.motionDebugOverlay);
this.selected[ent] = 1;
}
this.dirty = true;
};
EntitySelection.prototype.addList = function(ents)
@ -48,6 +55,7 @@ EntitySelection.prototype.addList = function(ents)
}
_setHighlight(added, g_ActiveSelectionColour);
_setMotionOverlay(added, this.motionDebugOverlay);
this.dirty = true;
};
EntitySelection.prototype.reset = function()
@ -55,6 +63,7 @@ EntitySelection.prototype.reset = function()
_setHighlight(this.toList(), g_InactiveSelectionColour);
_setMotionOverlay(this.toList(), false);
this.selected = {};
this.dirty = true;
};
EntitySelection.prototype.toList = function()

View File

@ -5,14 +5,27 @@ var g_DevSettings = {
function init(initData, hotloadData)
{
if (hotloadData)
{
g_Selection.selected = hotloadData.selection;
}
else
{
// Starting for the first time:
startMusic();
}
onSimulationUpdate();
}
function leaveGame()
{
stopMusic();
endGame();
Engine.SwitchGuiPage("page_pregame.xml");
}
// Return some data that we'll use when hotloading this file after changes
function getHotloadData()
{
@ -26,10 +39,16 @@ function onTick()
// player checks (once it has some player checks)
updateCursor();
// If the selection changed, we need to regenerate the sim display
if (g_Selection.dirty)
onSimulationUpdate();
}
function onSimulationUpdate()
{
g_Selection.dirty = false;
var simState = Engine.GuiInterfaceCall("GetSimulationState");
// If we're called during init when the game is first loading, there will be

View File

@ -6,12 +6,9 @@
<script file="gui/session_new/session.js"/>
<script file="gui/session_new/selection.js"/>
<script file="gui/session_new/input.js"/>
<script file="gui/session_new/music.js"/>
<object name="sn" hotkey="session.gui.toggle">
<action on="Load">
initSession();
</action>
<action on="Tick">
onTick();
</action>
@ -32,10 +29,6 @@
hotkey="leave"
>
<action on="Press"><![CDATA[
function leaveGame() {
endGame();
Engine.SwitchGuiPage("page_pregame.xml");
}
messageBox(400, 200, "Do you really want to quit?", "Confirmation", 0,
["Yes", "No!"], [leaveGame, null]);
]]></action>

View File

@ -203,9 +203,12 @@ CGameView::CGameView(CGame *pGame):
CGameView::~CGameView()
{
g_Selection.ClearSelection();
g_Mouseover.Clear();
g_BuildingPlacer.Deactivate();
if (!g_UseSimulation2)
{
g_Selection.ClearSelection();
g_Mouseover.Clear();
g_BuildingPlacer.Deactivate();
}
UnloadResources();
delete m;

View File

@ -454,28 +454,31 @@ void CMapWriter::WriteXML(const VfsPath& filename,
}
}
const std::list<MapTriggerGroup>& groups = g_TriggerManager.GetAllTriggerGroups();
std::list<MapTriggerGroup> rootChildren;
std::list<MapTriggerGroup>::const_iterator root = std::find( groups.begin(), groups.end(), L"Triggers" );
if (!g_UseSimulation2)
{
const std::list<MapTriggerGroup>& groups = g_TriggerManager.GetAllTriggerGroups();
std::list<MapTriggerGroup> rootChildren;
std::list<MapTriggerGroup>::const_iterator root = std::find( groups.begin(), groups.end(), L"Triggers" );
if ( root == groups.end() )
{
XML_Element("Triggers");
}
else
{
std::for_each(rootChildren.begin(), rootChildren.end(), CopyIfRootChild(rootChildren));
XML_Element("Triggers");
for ( std::list<MapTriggerGroup>::const_iterator it = rootChildren.begin();
it != rootChildren.end(); ++it )
if ( root == groups.end() )
{
WriteTriggerGroup(xml_file_, *it, groups);
XML_Element("Triggers");
}
for ( std::list<MapTrigger>::const_iterator it = root->triggers.begin();
it != root->triggers.end(); ++it )
else
{
WriteTrigger(xml_file_, *it);
std::for_each(rootChildren.begin(), rootChildren.end(), CopyIfRootChild(rootChildren));
XML_Element("Triggers");
for ( std::list<MapTriggerGroup>::const_iterator it = rootChildren.begin();
it != rootChildren.end(); ++it )
{
WriteTriggerGroup(xml_file_, *it, groups);
}
for ( std::list<MapTrigger>::const_iterator it = root->triggers.begin();
it != root->triggers.end(); ++it )
{
WriteTrigger(xml_file_, *it);
}
}
}
}

View File

@ -108,12 +108,14 @@ void CMiniMap::HandleMessage(const SGUIMessage &Message)
}
case GUIM_MOUSE_ENTER:
{
g_Selection.m_mouseOverMM = true;
if (!g_UseSimulation2)
g_Selection.m_mouseOverMM = true;
break;
}
case GUIM_MOUSE_LEAVE:
{
g_Selection.m_mouseOverMM = false;
if (!g_UseSimulation2)
g_Selection.m_mouseOverMM = false;
m_Clicking = false;
break;
}
@ -584,26 +586,33 @@ void CMiniMap::RebuildLOSTexture()
{
PROFILE_START("rebuild minimap: los");
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
CPlayer* player = g_Game->GetLocalPlayer();
ssize_t x = 0;
ssize_t y = 0;
ssize_t w = m_MapSize - 1;
ssize_t h = m_MapSize - 1;
for(ssize_t j = 0; j < h; j++)
if (g_UseSimulation2)
{
u8 *dataPtr = m_LOSData + ((y + j) * (m_MapSize - 1)) + x;
for(ssize_t i = 0; i < w; i++)
memset(m_LOSData, 0, w*h);
}
else
{
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
CPlayer* player = g_Game->GetLocalPlayer();
for(ssize_t j = 0; j < h; j++)
{
ELOSStatus status = losMgr->GetStatus(i, j, player);
if(status == LOS_UNEXPLORED)
*dataPtr++ = 0xff;
else if(status == LOS_EXPLORED)
*dataPtr++ = (u8) (0xff * 0.3f);
else
*dataPtr++ = 0;
u8 *dataPtr = m_LOSData + ((y + j) * (m_MapSize - 1)) + x;
for(ssize_t i = 0; i < w; i++)
{
ELOSStatus status = losMgr->GetStatus(i, j, player);
if(status == LOS_UNEXPLORED)
*dataPtr++ = 0xff;
else if(status == LOS_EXPLORED)
*dataPtr++ = (u8) (0xff * 0.3f);
else
*dataPtr++ = 0;
}
}
}

View File

@ -284,12 +284,15 @@ static void Frame()
g_Game->GetView()->Update(float(TimeSinceLastFrame));
}
PROFILE_START( "selection and interaction ui" );
// TODO Where does GameView end and other things begin?
g_Mouseover.Update( TimeSinceLastFrame );
g_Selection.Update();
g_BuildingPlacer.Update( TimeSinceLastFrame );
PROFILE_END( "selection and interaction ui" );
if (!g_UseSimulation2)
{
PROFILE_START( "selection and interaction ui" );
// TODO Where does GameView end and other things begin?
g_Mouseover.Update( TimeSinceLastFrame );
g_Selection.Update();
g_BuildingPlacer.Update( TimeSinceLastFrame );
PROFILE_END( "selection and interaction ui" );
}
PROFILE_START( "sound update" );
CCamera* camera = g_Game->GetView()->GetCamera();

View File

@ -70,7 +70,7 @@ CGame *g_Game=NULL;
**/
CGame::CGame():
m_World(new CWorld(this)),
m_Simulation(new CSimulation(this)),
m_Simulation(g_UseSimulation2 ? NULL : new CSimulation(this)),
m_Simulation2(g_UseSimulation2 ? new CSimulation2(&m_World->GetUnitManager(), m_World->GetTerrain()) : NULL),
m_GameView(new CGameView(this)),
m_pLocalPlayer(NULL),
@ -132,7 +132,8 @@ PSRETURN CGame::RegisterInit(CGameAttributes* pAttribs)
// some point to be stored in the world object?
m_GameView->RegisterInit(pAttribs);
m_World->RegisterInit(pAttribs);
m_Simulation->RegisterInit(pAttribs);
if (!g_UseSimulation2)
m_Simulation->RegisterInit(pAttribs);
LDR_EndRegistering();
return 0;
}
@ -240,9 +241,14 @@ bool CGame::Update(double deltaTime, bool doInterpolate)
bool ok = true;
if (g_UseSimulation2)
m_Simulation2->Update(deltaTime);
{
if (m_Simulation2->Update(deltaTime))
g_GUI->SendEventToAll("SimulationUpdate");
}
else
{
ok = m_Simulation->Update(deltaTime);
}
if (doInterpolate)
{
@ -252,8 +258,6 @@ bool CGame::Update(double deltaTime, bool doInterpolate)
m_Simulation->Interpolate(deltaTime);
}
g_GUI->SendEventToAll("SimulationUpdate");
// TODO Detect game over and bring up the summary screen or something
// ^ Quick game over hack is implemented, no summary screen however
/*if (m_World->GetEntityManager().GetDeath())

View File

@ -63,6 +63,7 @@
#include "simulation/Entity.h"
#include "simulation/EntityManager.h"
#include "simulation/EntityTemplateCollection.h"
#include "simulation/Scheduler.h"
#include "simulation2/Simulation2.h"
@ -237,7 +238,11 @@ void Render()
ogl_WarnIfError();
if (g_Game && g_Game->IsGameStarted())
if (g_Game && g_Game->IsGameStarted() && g_UseSimulation2)
{
g_Game->GetView()->Render();
}
else if (g_Game && g_Game->IsGameStarted() && !g_UseSimulation2)
{
g_Game->GetView()->Render();
@ -259,7 +264,7 @@ void Render()
g_Mouseover.RenderSelectionOutlines();
g_Selection.RenderSelectionOutlines();
PROFILE_END( "render entity outlines" );
PROFILE_START( "render entity auras" );
g_Mouseover.RenderAuras();
g_Selection.RenderAuras();
@ -383,7 +388,7 @@ void Render()
ogl_WarnIfError();
if (g_Game && g_Game->IsGameStarted())
if (g_Game && g_Game->IsGameStarted() && !g_UseSimulation2)
{
PROFILE( "render selection overlays" );
g_Mouseover.RenderOverlays();
@ -393,7 +398,7 @@ void Render()
ogl_WarnIfError();
// Draw the cursor (or set the Windows cursor, on Windows)
CStrW cursorName = g_BuildingPlacer.m_active ? L"action-build" : g_CursorName;
CStrW cursorName = (!g_UseSimulation2 && g_BuildingPlacer.m_active) ? L"action-build" : g_CursorName;
if (cursorName.empty())
cursor_draw(NULL, g_mouse_x, g_mouse_y);
else
@ -744,16 +749,24 @@ void Shutdown(int flags)
if (! (flags & INIT_NO_SIM))
{
TIMER_BEGIN(L"shutdown mouse stuff");
delete &g_Mouseover;
delete &g_Selection;
delete &g_BuildingPlacer;
TIMER_END(L"shutdown mouse stuff");
if (g_UseSimulation2)
{
delete &g_GameAttributes;
delete &g_EntityTemplateCollection;
}
else
{
TIMER_BEGIN(L"shutdown mouse stuff");
delete &g_Mouseover;
delete &g_Selection;
delete &g_BuildingPlacer;
TIMER_END(L"shutdown mouse stuff");
TIMER_BEGIN(L"shutdown game scripting stuff");
delete &g_GameAttributes;
SimulationShutdown();
TIMER_END(L"shutdown game scripting stuff");
TIMER_BEGIN(L"shutdown game scripting stuff");
delete &g_GameAttributes;
SimulationShutdown();
TIMER_END(L"shutdown game scripting stuff");
}
}
// destroy actor related stuff
@ -1001,15 +1014,23 @@ void Init(const CmdLineArgs& args, int flags)
if (! (flags & INIT_NO_SIM))
{
// This needs to be done after the renderer has loaded all its actors...
SimulationInit();
if (g_UseSimulation2)
{
TIMER(L"Init_miscgamesection");
new CSelectedEntities;
new CMouseoverEntities;
new CBuildingPlacer;
new CEntityTemplateCollection; // this is just needed for loading old maps
new CGameAttributes;
}
else
{
SimulationInit();
{
TIMER(L"Init_miscgamesection");
new CSelectedEntities;
new CMouseoverEntities;
new CBuildingPlacer;
new CGameAttributes;
}
}
// Register a few Game/Network JS globals
g_ScriptingHost.SetGlobal("g_GameAttributes", OBJECT_TO_JSVAL(g_GameAttributes.GetScript()));

View File

@ -47,6 +47,7 @@
#include "simulation/TerritoryManager.h"
#include "simulation/TriggerManager.h"
#include "simulation/Projectile.h"
#include "simulation2/Simulation2.h"
#define LOG_CATEGORY L"world"
@ -92,9 +93,12 @@ void CWorld::Initialize(CGameAttributes *pAttribs)
try {
reader = new CMapReader;
CTriggerManager* pTriggerManager = NULL;
if (!g_UseSimulation2)
pTriggerManager = &g_TriggerManager;
reader->LoadMap(mapfilename, m_Terrain, m_UnitManager, g_Renderer.GetWaterManager(),
g_Renderer.GetSkyManager(), &g_LightEnv, m_pGame->GetView()->GetCamera(), m_pGame->GetView()->GetCinema(),
&g_TriggerManager, m_pGame->GetSimulation2(), m_EntityManager);
pTriggerManager, m_pGame->GetSimulation2(), m_EntityManager);
// fails immediately, or registers for delay loading
} catch (PSERROR_File&) {
delete reader;

View File

@ -34,6 +34,7 @@
#include "simulation/LOSManager.h"
#include "graphics/Patch.h"
#include "graphics/Terrain.h"
#include "simulation2/Simulation2.h"
const ssize_t BlendOffsets[8][2] = {
{ 0, -1 },
@ -434,7 +435,7 @@ void CPatchRData::Update()
ssize_t vsize=PATCH_SIZE+1;
SColor4ub baseColour = terrain->GetBaseColour();
if (g_Game)
if (g_Game && !g_UseSimulation2)
{
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();

View File

@ -37,6 +37,7 @@
#include "ps/World.h"
#include "simulation/LOSManager.h"
#include "simulation2/Simulation2.h"
#include "renderer/PatchRData.h"
#include "renderer/Renderer.h"
@ -602,18 +603,21 @@ void TerrainRenderer::RenderWater()
-100.0f, WaterMgr->m_WaterMaxAlpha);
float losMod = 1.0f;
for(size_t k=0; k<4; k++)
if (!g_UseSimulation2)
{
ssize_t tx = ix - DX[k];
ssize_t tz = iz - DZ[k];
if(tx >= 0 && tz >= 0 && tx <= mapSize-2 && tz <= mapSize-2)
for(size_t k=0; k<4; k++)
{
ELOSStatus s = losMgr->GetStatus(tx, tz, g_Game->GetLocalPlayer());
if(s == LOS_EXPLORED && losMod > 0.7f)
losMod = 0.7f;
else if(s==LOS_UNEXPLORED && losMod > 0.0f)
losMod = 0.0f;
ssize_t tx = ix - DX[k];
ssize_t tz = iz - DZ[k];
if(tx >= 0 && tz >= 0 && tx <= mapSize-2 && tz <= mapSize-2)
{
ELOSStatus s = losMgr->GetStatus(tx, tz, g_Game->GetLocalPlayer());
if(s == LOS_EXPLORED && losMod > 0.7f)
losMod = 0.7f;
else if(s==LOS_UNEXPLORED && losMod > 0.0f)
losMod = 0.0f;
}
}
}

View File

@ -86,7 +86,7 @@ public:
bool LoadScripts(const VfsPath& path);
LibError ReloadChangedFile(const VfsPath& path);
void Update(float frameTime);
bool Update(float frameTime);
void Interpolate(float frameTime);
CSimContext m_SimContext;
@ -141,7 +141,7 @@ LibError CSimulation2Impl::ReloadChangedFile(const VfsPath& path)
return INFO::OK;
}
void CSimulation2Impl::Update(float frameTime)
bool CSimulation2Impl::Update(float frameTime)
{
// TODO: Use CTurnManager
m_DeltaTime += frameTime;
@ -168,7 +168,10 @@ void CSimulation2Impl::Update(float frameTime)
m_ComponentManager.FlushDestroyedComponents();
++m_TurnNumber;
return true;
}
return false;
}
void CSimulation2Impl::Interpolate(float frameTime)
@ -255,9 +258,9 @@ void CSimulation2::InitGame(const CScriptVal& data)
GetScriptInterface().CallFunction(GetScriptInterface().GetGlobalObject(), "InitGame", data, ret);
}
void CSimulation2::Update(float frameTime)
bool CSimulation2::Update(float frameTime)
{
m->Update(frameTime);
return m->Update(frameTime);
}
void CSimulation2::Interpolate(float frameTime)

View File

@ -89,7 +89,7 @@ public:
*/
void InitGame(const CScriptVal& data);
void Update(float frameTime);
bool Update(float frameTime);
void Interpolate(float frameTime);
void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling);

View File

@ -92,8 +92,11 @@ namespace
ret = g_Game->ReallyStartGame();
debug_assert(ret == PSRETURN_OK);
// Make sure entities get rendered in the correct location
g_Game->GetSimulation()->Interpolate(0.0);
if (!g_UseSimulation2)
{
// Make sure entities get rendered in the correct location
g_Game->GetSimulation()->Interpolate(0.0);
}
}
}

View File

@ -25,6 +25,7 @@
#include "ps/Game.h"
#include "graphics/GameView.h"
#include "graphics/CinemaTrack.h"
#include "simulation2/Simulation2.h"
namespace AtlasMessage {
@ -234,6 +235,9 @@ MapTriggerGroup AtlasToGroup(const sTriggerGroup& group)
std::vector<sTriggerGroup> GetCurrentTriggers()
{
if (g_UseSimulation2)
return std::vector<sTriggerGroup>();
const std::list<MapTriggerGroup>& groups = g_TriggerManager.GetAllTriggerGroups();
std::vector<sTriggerGroup> atlasGroups;
@ -244,6 +248,9 @@ std::vector<sTriggerGroup> GetCurrentTriggers()
void SetCurrentTriggers(const std::vector<sTriggerGroup>& groups)
{
if (g_UseSimulation2)
return;
std::list<MapTriggerGroup> engineGroups;
for ( std::vector<sTriggerGroup>::const_iterator it = groups.begin(); it != groups.end(); ++it )
engineGroups.push_back( AtlasToGroup(*it) );
@ -252,6 +259,9 @@ void SetCurrentTriggers(const std::vector<sTriggerGroup>& groups)
QUERYHANDLER(GetTriggerData)
{
if (g_UseSimulation2)
return;
const std::list<CTriggerCondition>& conditions = g_TriggerManager.GetAllConditions();
const std::list<CTriggerEffect>& effects = g_TriggerManager.GetAllEffects();
std::vector<sTriggerSpec> atlasConditions;
@ -269,6 +279,9 @@ QUERYHANDLER(GetTriggerData)
QUERYHANDLER(GetTriggerChoices)
{
if (g_UseSimulation2)
return;
CStrW selectedName(*msg->name);
std::vector<std::wstring> choices = g_TriggerManager.GetTriggerChoices(selectedName);
std::vector<std::wstring> translations = g_TriggerManager.GetTriggerTranslations(selectedName);

View File

@ -178,9 +178,10 @@ void ViewGame::Update(float frameLength)
if (m_SpeedMultiplier == 0.f)
{
// Update unit interpolation
g_Game->GetSimulation()->Interpolate(0.0);
if (g_UseSimulation2)
g_Game->GetSimulation2()->Interpolate(0.0);
else
g_Game->GetSimulation()->Interpolate(0.0);
}
else
{
@ -202,13 +203,18 @@ void ViewGame::Update(float frameLength)
// Interpolate the graphics - we only want to do this once per visual frame,
// not in every call to g_Game->Update
g_Game->GetSimulation()->Interpolate(actualFrameLength);
if (g_UseSimulation2)
{
g_Game->GetSimulation2()->Interpolate(actualFrameLength);
}
else
{
g_Game->GetSimulation()->Interpolate(actualFrameLength);
// If we still couldn't keep up, just drop the sim rate instead of building
// up a (potentially very large) backlog of required updates
g_Game->GetSimulation()->DiscardMissedUpdates();
// If we still couldn't keep up, just drop the sim rate instead of building
// up a (potentially very large) backlog of required updates
g_Game->GetSimulation()->DiscardMissedUpdates();
}
}
// Cinematic motion should be independent of simulation update, so we can