Finished first EA Version #1
@@ -19,7 +19,7 @@ public partial class GameData
|
|||||||
public static float tileWidth = 6;
|
public static float tileWidth = 6;
|
||||||
public static float tileHeight = 4;
|
public static float tileHeight = 4;
|
||||||
public static SortedDictionary<string, ItemData> availableItems = ResourceLoader.LoadItems();
|
public static SortedDictionary<string, ItemData> availableItems = ResourceLoader.LoadItems();
|
||||||
public static Dictionary<string, ResearchData> availableResearch = ResourceLoader.LoadResearch();
|
public static Dictionary<string, Research> availableResearch = ResourceLoader.LoadResearch();
|
||||||
|
|
||||||
//--- PLAYER ADJUSTABLE VALUES ---
|
//--- PLAYER ADJUSTABLE VALUES ---
|
||||||
//Color used in primary objects (e.g. Robots)
|
//Color used in primary objects (e.g. Robots)
|
||||||
|
|||||||
@@ -102,18 +102,18 @@ public partial class ResourceLoader
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, ResearchData> LoadResearch()
|
public static Dictionary<string, Research> LoadResearch()
|
||||||
{
|
{
|
||||||
|
|
||||||
FileAccess file = FileAccess.Open("res://Assets/Research.json", FileAccess.ModeFlags.Read);
|
FileAccess file = FileAccess.Open("res://Assets/Research.json", FileAccess.ModeFlags.Read);
|
||||||
string json = file.GetAsText();
|
string json = file.GetAsText();
|
||||||
|
|
||||||
Dictionary<string, ResearchData> result = new();
|
Dictionary<string, Research> result = new();
|
||||||
|
|
||||||
List<ResearchData> researches = JsonSerializer.Deserialize<List<ResearchData>>(json);
|
List<ResearchData> researches = JsonSerializer.Deserialize<List<ResearchData>>(json);
|
||||||
foreach (ResearchData research in researches)
|
foreach (ResearchData research in researches)
|
||||||
{
|
{
|
||||||
result.Add(research.Id, research);
|
result.Add(research.Id, new Research(research));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -3,9 +3,15 @@ using Godot;
|
|||||||
public class Research
|
public class Research
|
||||||
{
|
{
|
||||||
public ResearchData data;
|
public ResearchData data;
|
||||||
public bool isResearched = false;
|
|
||||||
public double elapsedResearchTime = 0;
|
public double elapsedResearchTime = 0;
|
||||||
public bool paidResources = false;
|
public bool paidResources = false;
|
||||||
|
public ResearchState state;
|
||||||
|
|
||||||
|
public Research(ResearchData data)
|
||||||
|
{
|
||||||
|
this.data = data;
|
||||||
|
state = ResearchState.UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
public ResearchResult Execute(double delta)
|
public ResearchResult Execute(double delta)
|
||||||
{
|
{
|
||||||
@@ -20,7 +26,7 @@ public class Research
|
|||||||
elapsedResearchTime += delta;
|
elapsedResearchTime += delta;
|
||||||
if (elapsedResearchTime >= data.CraftTime)
|
if (elapsedResearchTime >= data.CraftTime)
|
||||||
{
|
{
|
||||||
isResearched = true;
|
state = ResearchState.RESEARCHED;
|
||||||
return ResearchResult.FINISHED;
|
return ResearchResult.FINISHED;
|
||||||
}
|
}
|
||||||
return ResearchResult.RESEARCHING;
|
return ResearchResult.RESEARCHING;
|
||||||
|
|||||||
@@ -1,49 +1,118 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using Godot.Collections;
|
||||||
|
|
||||||
public partial class ResearchList : PanelContainer
|
public partial class ResearchList : PanelContainer
|
||||||
{
|
{
|
||||||
[Export] GraphEdit researchGraph;
|
[Export] private GraphEdit researchGraph;
|
||||||
|
|
||||||
|
private const float StartXDivisor = 32f;
|
||||||
|
private const float StartYDivisor = 4f;
|
||||||
|
private const float NodeSpacingMultiplier = 10f;
|
||||||
|
|
||||||
|
private List<string> reloadKeys = new List<string>();
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
foreach (ResearchData research in GameData.availableResearch.Values)
|
RecalculateResearchStates();
|
||||||
{
|
SetupGraph();
|
||||||
researchGraph.AddChild(CreateItemNode(research.Id, research.Texture));
|
|
||||||
}
|
}
|
||||||
foreach (ResearchData research in GameData.availableResearch.Values)
|
|
||||||
|
public void SetupGraph()
|
||||||
{
|
{
|
||||||
|
reloadKeys = new List<string>();
|
||||||
|
ClearGraph();
|
||||||
|
CreateResearchNodes();
|
||||||
|
CreateResearchConnections();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearGraph()
|
||||||
|
{
|
||||||
|
foreach (Dictionary connection in researchGraph.GetConnectionList())
|
||||||
|
{
|
||||||
|
researchGraph.DisconnectNode(
|
||||||
|
connection["from_node"].AsStringName(),
|
||||||
|
(int)connection["from_port"],
|
||||||
|
connection["to_node"].AsStringName(),
|
||||||
|
(int)connection["to_port"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Node child in researchGraph.GetChildren())
|
||||||
|
{
|
||||||
|
if (child is GraphNode)
|
||||||
|
{
|
||||||
|
researchGraph.RemoveChild(child);
|
||||||
|
child.QueueFree();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateResearchNodes()
|
||||||
|
{
|
||||||
|
foreach (Research research in GameData.availableResearch.Values)
|
||||||
|
{
|
||||||
|
GD.Print(research.state);
|
||||||
|
GraphNode node = CreateResearchNode(
|
||||||
|
research.data.Id,
|
||||||
|
research.data.Texture,
|
||||||
|
research.state
|
||||||
|
);
|
||||||
|
|
||||||
|
researchGraph.AddChild(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateResearchConnections()
|
||||||
|
{
|
||||||
|
foreach (Research research in GameData.availableResearch.Values)
|
||||||
|
{
|
||||||
|
string prerequisite = research.data.Research;
|
||||||
|
string current = research.data.Id;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(prerequisite))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!researchGraph.HasNode(prerequisite) || !researchGraph.HasNode(current))
|
||||||
|
continue;
|
||||||
|
|
||||||
researchGraph.ConnectNode(
|
researchGraph.ConnectNode(
|
||||||
research.Research,
|
prerequisite,
|
||||||
0,
|
0,
|
||||||
research.Id,
|
current,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Process(double delta)
|
private GraphNode CreateResearchNode(string id, string texturePath, ResearchState state)
|
||||||
{
|
{
|
||||||
|
Texture2D texture = GD.Load<Texture2D>(texturePath);
|
||||||
|
Color stateColor = GetColorByState(state);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private GraphNode CreateItemNode(string id, string texturePath)
|
|
||||||
{
|
|
||||||
Vector2 viewportSize = GetViewport().GetVisibleRect().Size;
|
|
||||||
TextureRect icon = new TextureRect
|
TextureRect icon = new TextureRect
|
||||||
{
|
{
|
||||||
Texture = GD.Load<Texture2D>(texturePath),
|
Texture = texture,
|
||||||
StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered
|
StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered,
|
||||||
|
CustomMinimumSize = new Vector2(64, 64),
|
||||||
|
SelfModulate = stateColor
|
||||||
};
|
};
|
||||||
//Step 1: Place the node in the visible field for the player
|
|
||||||
Vector2 nodePosition = new Vector2(viewportSize.X / 32, viewportSize.Y / 4);
|
Button button = new Button
|
||||||
//Step 2: Modify position by nodeIndex
|
{
|
||||||
nodePosition = nodePosition + new Vector2(GameData.availableResearch.Count * -icon.Texture.GetWidth() + researchGraph.GetChildCount() * icon.Texture.GetWidth() * 10, 0);
|
Text = "Research",
|
||||||
|
Disabled = state != ResearchState.AVAILABLE
|
||||||
|
};
|
||||||
|
|
||||||
|
button.Pressed += () => OnResearchPressed(id);
|
||||||
|
|
||||||
GraphNode node = new GraphNode
|
GraphNode node = new GraphNode
|
||||||
{
|
{
|
||||||
Name = id,
|
Name = id,
|
||||||
Title = id,
|
Title = id,
|
||||||
PositionOffset = nodePosition
|
PositionOffset = GetNodePosition(texture),
|
||||||
|
SelfModulate = stateColor
|
||||||
};
|
};
|
||||||
|
|
||||||
node.SetSlot(
|
node.SetSlot(
|
||||||
@@ -57,7 +126,86 @@ public partial class ResearchList : PanelContainer
|
|||||||
);
|
);
|
||||||
|
|
||||||
node.AddChild(icon);
|
node.AddChild(icon);
|
||||||
|
node.AddChild(button);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vector2 GetNodePosition(Texture2D texture)
|
||||||
|
{
|
||||||
|
Vector2 viewportSize = GetViewport().GetVisibleRect().Size;
|
||||||
|
|
||||||
|
float textureWidth = texture?.GetWidth() ?? 64f;
|
||||||
|
|
||||||
|
Vector2 startPosition = new Vector2(
|
||||||
|
viewportSize.X / StartXDivisor,
|
||||||
|
viewportSize.Y / StartYDivisor
|
||||||
|
);
|
||||||
|
|
||||||
|
float xOffset =
|
||||||
|
GameData.availableResearch.Count * -textureWidth +
|
||||||
|
researchGraph.GetChildCount() * textureWidth * NodeSpacingMultiplier;
|
||||||
|
|
||||||
|
return startPosition + new Vector2(xOffset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnResearchPressed(string id)
|
||||||
|
{
|
||||||
|
GameData.availableResearch[id].state = ResearchState.RESEARCHED;
|
||||||
|
RecalculateResearchStates();
|
||||||
|
SetupGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecalculateResearchStates()
|
||||||
|
{
|
||||||
|
bool changedState;
|
||||||
|
foreach (string key in GameData.availableResearch.Keys)
|
||||||
|
{
|
||||||
|
changedState = false;
|
||||||
|
if (reloadKeys.Contains(key)) continue;
|
||||||
|
reloadKeys.Add(key);
|
||||||
|
|
||||||
|
//Already researched
|
||||||
|
if (GameData.availableResearch[key].state == ResearchState.RESEARCHED)
|
||||||
|
{
|
||||||
|
changedState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//No previous research needed
|
||||||
|
if (GameData.availableResearch[key].data.Research.Length <= 0)
|
||||||
|
{
|
||||||
|
GameData.availableResearch[key].state = ResearchState.RESEARCHED;
|
||||||
|
changedState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Previous research is unlocked
|
||||||
|
if (!changedState && GameData.availableResearch[GameData.availableResearch[key].data.Research].state == ResearchState.RESEARCHED)
|
||||||
|
{
|
||||||
|
GameData.availableResearch[key].state = ResearchState.AVAILABLE;
|
||||||
|
changedState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changedState)
|
||||||
|
{
|
||||||
|
//All others are locked
|
||||||
|
GameData.availableResearch[key].state = ResearchState.LOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reloadKeys.Count != GameData.availableResearch.Keys.Count)
|
||||||
|
{
|
||||||
|
RecalculateResearchStates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color GetColorByState(ResearchState state)
|
||||||
|
{
|
||||||
|
return state switch
|
||||||
|
{
|
||||||
|
ResearchState.AVAILABLE => Colors.White,
|
||||||
|
ResearchState.LOCKED => new Color(0.6f, 0.6f, 0.6f, 0.5f),
|
||||||
|
ResearchState.RESEARCHED => new Color(0.7f, 1f, 0.7f, 1f),
|
||||||
|
_ => Colors.Red
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
public enum ResearchState
|
||||||
|
{
|
||||||
|
UNDEFINED,
|
||||||
|
RESEARCHED,
|
||||||
|
AVAILABLE,
|
||||||
|
LOCKED
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://b57yhucbav37c
|
||||||
Reference in New Issue
Block a user