1
0
forked from 0ad/0ad

Stop units walking outside the edges of circular maps.

Switch the GUI between square/circular minimap automatically.

This was SVN commit r8500.
This commit is contained in:
Ykkrosh 2010-10-30 18:25:34 +00:00
parent 21b0504ca5
commit 1840bb3507
10 changed files with 84 additions and 7 deletions

View File

@ -192,18 +192,35 @@ function onSimulationUpdate()
g_TemplateData = {}; g_TemplateData = {};
var simState = Engine.GuiInterfaceCall("GetSimulationState"); var simState = Engine.GuiInterfaceCall("GetSimulationState");
// If we're called during init when the game is first loading, there will be no simulation yet, so do nothing // If we're called during init when the game is first loading, there will be no simulation yet, so do nothing
if (!simState) if (!simState)
return; return;
handleNotifications(); handleNotifications();
updateMinimap(simState);
updateDebug(simState); updateDebug(simState);
updatePlayerDisplay(simState); updatePlayerDisplay(simState);
updateSelectionDetails(); updateSelectionDetails();
} }
function updateMinimap(simState)
{
if (simState.circularMap)
{
getGUIObjectByName("minimap").circular = true;
getGUIObjectByName("minimapSquareOverlay").hidden = true;
getGUIObjectByName("minimapCircleOverlay").hidden = false;
}
else
{
getGUIObjectByName("minimap").circular = false;
getGUIObjectByName("minimapSquareOverlay").hidden = false;
getGUIObjectByName("minimapCircleOverlay").hidden = true;
}
}
function updateDebug(simState) function updateDebug(simState)
{ {
var debug = getGUIObjectByName("debug"); var debug = getGUIObjectByName("debug");

View File

@ -409,9 +409,9 @@
> >
<action on="WorldClick">handleMinimapEvent(arguments[0]);</action> <action on="WorldClick">handleMinimapEvent(arguments[0]);</action>
</object> </object>
<!-- <object size="10 10 100%-10 100%-10" type="image" sprite="glassSquareMap" ghost="true"/>--> <object name="minimapSquareOverlay" size="10 10 100%-10 100%-10" type="image" sprite="glassSquareMap" ghost="true"/>
<object size="10 10 100%-10 100%-10" type="image" sprite="stretched:session/minimap_circle.png" ghost="true"/> <object name="minimapCircleOverlay" size="10 10 100%-10 100%-10" type="image" sprite="stretched:session/minimap_circle.png" ghost="true" hidden="true"/>
</object> </object>
<!-- ================================ ================================ --> <!-- ================================ ================================ -->

View File

@ -45,6 +45,12 @@ GuiInterface.prototype.GetSimulationState = function(player)
ret.players.push(playerData); ret.players.push(playerData);
} }
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
if (cmpRangeManager)
{
ret.circularMap = cmpRangeManager.GetLosCircular();
}
return ret; return ret;
}; };

View File

@ -31,6 +31,10 @@ function LoadMapSettings(settings)
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
if (cmpRangeManager) if (cmpRangeManager)
cmpRangeManager.SetLosCircular(true); cmpRangeManager.SetLosCircular(true);
var cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager);
if (cmpObstructionManager)
cmpObstructionManager.SetPassabilityCircular(true);
} }
var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
@ -41,4 +45,4 @@ function LoadMapSettings(settings)
cmpEndGameManager.Start(); cmpEndGameManager.Start();
} }
Engine.RegisterGlobal("LoadMapSettings", LoadMapSettings); Engine.RegisterGlobal("LoadMapSettings", LoadMapSettings);

View File

@ -122,6 +122,8 @@ public:
u32 m_UnitShapeNext; // next allocated id u32 m_UnitShapeNext; // next allocated id
u32 m_StaticShapeNext; u32 m_StaticShapeNext;
bool m_PassabilityCircular;
entity_pos_t m_WorldX0; entity_pos_t m_WorldX0;
entity_pos_t m_WorldZ0; entity_pos_t m_WorldZ0;
entity_pos_t m_WorldX1; entity_pos_t m_WorldX1;
@ -142,6 +144,8 @@ public:
m_DirtyID = 1; // init to 1 so default-initialised grids are considered dirty m_DirtyID = 1; // init to 1 so default-initialised grids are considered dirty
m_PassabilityCircular = false;
m_WorldX0 = m_WorldZ0 = m_WorldX1 = m_WorldZ1 = entity_pos_t::Zero(); m_WorldX0 = m_WorldZ0 = m_WorldX1 = m_WorldZ1 = entity_pos_t::Zero();
// Initialise with bogus values (these will get replaced when // Initialise with bogus values (these will get replaced when
@ -164,6 +168,8 @@ public:
serialize.NumberU32_Unbounded("unit shape next", m_UnitShapeNext); serialize.NumberU32_Unbounded("unit shape next", m_UnitShapeNext);
serialize.NumberU32_Unbounded("static shape next", m_StaticShapeNext); serialize.NumberU32_Unbounded("static shape next", m_StaticShapeNext);
serialize.Bool("circular", m_PassabilityCircular);
serialize.NumberFixed_Unbounded("world x0", m_WorldX0); serialize.NumberFixed_Unbounded("world x0", m_WorldX0);
serialize.NumberFixed_Unbounded("world z0", m_WorldZ0); serialize.NumberFixed_Unbounded("world z0", m_WorldZ0);
serialize.NumberFixed_Unbounded("world x1", m_WorldX1); serialize.NumberFixed_Unbounded("world x1", m_WorldX1);
@ -388,6 +394,12 @@ public:
virtual void GetObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares); virtual void GetObstructionsInRange(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, std::vector<ObstructionSquare>& squares);
virtual bool FindMostImportantObstruction(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare& square); virtual bool FindMostImportantObstruction(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, ObstructionSquare& square);
virtual void SetPassabilityCircular(bool enabled)
{
m_PassabilityCircular = enabled;
MakeDirty();
}
virtual void SetDebugOverlay(bool enabled) virtual void SetDebugOverlay(bool enabled)
{ {
m_DebugOverlayEnabled = enabled; m_DebugOverlayEnabled = enabled;
@ -660,6 +672,27 @@ bool CCmpObstructionManager::Rasterise(Grid<u8>& grid)
grid.set(i, j, TILE_OBSTRUCTED | TILE_OUTOFBOUNDS); grid.set(i, j, TILE_OBSTRUCTED | TILE_OUTOFBOUNDS);
} }
if (m_PassabilityCircular)
{
for (u16 j = 0; j < grid.m_H; ++j)
{
for (u16 i = 0; i < grid.m_W; ++i)
{
// Based on CCmpRangeManager::LosIsOffWorld
// but tweaked since it's tile-based instead.
// This needs to be slightly tighter than the LOS circle,
// else units might get themselves lost in the SoD around the edge.
ssize_t dist2 = (i*2 + 1 - grid.m_W)*(i*2 + 1 - grid.m_W)
+ (j*2 + 1 - grid.m_H)*(j*2 + 1 - grid.m_H);
if (dist2 >= (grid.m_W-2)*(grid.m_H-2))
grid.set(i, j, TILE_OBSTRUCTED | TILE_OUTOFBOUNDS);
}
}
}
return true; return true;
} }

View File

@ -816,6 +816,11 @@ private:
ResetDerivedData(); ResetDerivedData();
} }
virtual bool GetLosCircular()
{
return m_LosCircular;
}
/** /**
* Returns whether the given vertex is outside the normal bounds of the world * Returns whether the given vertex is outside the normal bounds of the world
* (i.e. outside the range of a circular map) * (i.e. outside the range of a circular map)
@ -824,12 +829,12 @@ private:
{ {
if (m_LosCircular) if (m_LosCircular)
{ {
// With a circular map, vertex is off-world if hypot(i - size/2, j - size/2) > size/2: // With a circular map, vertex is off-world if hypot(i - size/2, j - size/2) >= size/2:
ssize_t dist2 = (i - m_TerrainVerticesPerSide/2)*(i - m_TerrainVerticesPerSide/2) ssize_t dist2 = (i - m_TerrainVerticesPerSide/2)*(i - m_TerrainVerticesPerSide/2)
+ (j - m_TerrainVerticesPerSide/2)*(j - m_TerrainVerticesPerSide/2); + (j - m_TerrainVerticesPerSide/2)*(j - m_TerrainVerticesPerSide/2);
if (dist2 >= m_TerrainVerticesPerSide*m_TerrainVerticesPerSide/4) if (dist2 >= (m_TerrainVerticesPerSide/2)*(m_TerrainVerticesPerSide/2))
return true; return true;
} }

View File

@ -22,5 +22,6 @@
#include "simulation2/system/InterfaceScripted.h" #include "simulation2/system/InterfaceScripted.h"
BEGIN_INTERFACE_WRAPPER(ObstructionManager) BEGIN_INTERFACE_WRAPPER(ObstructionManager)
DEFINE_INTERFACE_METHOD_1("SetPassabilityCircular", void, ICmpObstructionManager, SetPassabilityCircular, bool)
DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpObstructionManager, SetDebugOverlay, bool) DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpObstructionManager, SetDebugOverlay, bool)
END_INTERFACE_WRAPPER(ObstructionManager) END_INTERFACE_WRAPPER(ObstructionManager)

View File

@ -215,6 +215,11 @@ public:
*/ */
virtual ObstructionSquare GetObstruction(tag_t tag) = 0; virtual ObstructionSquare GetObstruction(tag_t tag) = 0;
/**
* Set the passability to be restricted to a circular map.
*/
virtual void SetPassabilityCircular(bool enabled) = 0;
/** /**
* Toggle the rendering of debug info. * Toggle the rendering of debug info.
*/ */

View File

@ -45,4 +45,5 @@ DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpRangeManager, SetDebugOve
DEFINE_INTERFACE_METHOD_1("SetLosRevealAll", void, ICmpRangeManager, SetLosRevealAll, bool) DEFINE_INTERFACE_METHOD_1("SetLosRevealAll", void, ICmpRangeManager, SetLosRevealAll, bool)
DEFINE_INTERFACE_METHOD_2("GetLosVisibility", std::string, ICmpRangeManager, GetLosVisibility_wrapper, entity_id_t, int) DEFINE_INTERFACE_METHOD_2("GetLosVisibility", std::string, ICmpRangeManager, GetLosVisibility_wrapper, entity_id_t, int)
DEFINE_INTERFACE_METHOD_1("SetLosCircular", void, ICmpRangeManager, SetLosCircular, bool) DEFINE_INTERFACE_METHOD_1("SetLosCircular", void, ICmpRangeManager, SetLosCircular, bool)
DEFINE_INTERFACE_METHOD_0("GetLosCircular", bool, ICmpRangeManager, GetLosCircular)
END_INTERFACE_WRAPPER(RangeManager) END_INTERFACE_WRAPPER(RangeManager)

View File

@ -249,6 +249,11 @@ public:
*/ */
virtual void SetLosCircular(bool enabled) = 0; virtual void SetLosCircular(bool enabled) = 0;
/**
* Returns whether the LOS is restricted to a circular map.
*/
virtual bool GetLosCircular() = 0;
DECLARE_INTERFACE_TYPE(RangeManager) DECLARE_INTERFACE_TYPE(RangeManager)
}; };