Add initial game code

This commit is contained in:
Aslan 2025-09-12 08:34:06 -04:00
parent f80a60e208
commit 1383997ebf
55 changed files with 1355 additions and 0 deletions

4
.editorconfig Normal file
View file

@ -0,0 +1,4 @@
root = true
[*]
charset = utf-8

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

7
Idle Starship.csproj Normal file
View file

@ -0,0 +1,7 @@
<Project Sdk="Godot.NET.Sdk/4.5.0-rc.2">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>IdleStarship</RootNamespace>
</PropertyGroup>
</Project>

19
Idle Starship.sln Normal file
View file

@ -0,0 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Idle Starship", "Idle Starship.csproj", "{3CFAAC77-A968-438F-8CDD-E4152B8DB981}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
ExportDebug|Any CPU = ExportDebug|Any CPU
ExportRelease|Any CPU = ExportRelease|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3CFAAC77-A968-438F-8CDD-E4152B8DB981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3CFAAC77-A968-438F-8CDD-E4152B8DB981}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3CFAAC77-A968-438F-8CDD-E4152B8DB981}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
{3CFAAC77-A968-438F-8CDD-E4152B8DB981}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
{3CFAAC77-A968-438F-8CDD-E4152B8DB981}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
{3CFAAC77-A968-438F-8CDD-E4152B8DB981}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
EndGlobalSection
EndGlobal

1
icon.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>

After

Width:  |  Height:  |  Size: 995 B

43
icon.svg.import Normal file
View file

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b1rrvmekhjw68"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

25
project.godot Normal file
View file

@ -0,0 +1,25 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Idle Starship"
run/main_scene="uid://h3dgo6me76t7"
config/features=PackedStringArray("4.5", "C#", "Mobile")
config/icon="res://icon.svg"
[dotnet]
project/assembly_name="Idle Starship"
[rendering]
renderer/rendering_method="mobile"
textures/vram_compression/import_etc2_astc=true

75
scenes/game.tscn Normal file
View file

@ -0,0 +1,75 @@
[gd_scene load_steps=4 format=3 uid="uid://u1kttqp08vjc"]
[ext_resource type="Script" uid="uid://bladckxyu6xmy" path="res://scripts/Controller.cs" id="1_lnu2h"]
[ext_resource type="Script" uid="uid://c0d47hdgdfsa6" path="res://scripts/GameManager.cs" id="1_yqjtg"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_yqjtg"]
[node name="Control" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_lnu2h")
[node name="Game" type="Node2D" parent="."]
[node name="GameManager" type="Node" parent="."]
script = ExtResource("1_yqjtg")
[node name="Container" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Top" type="HBoxContainer" parent="Container"]
layout_mode = 2
[node name="ExitToMenuButton" type="Button" parent="Container/Top"]
layout_mode = 2
text = "Exit to Menu"
[node name="Separator" type="Control" parent="Container/Top"]
layout_mode = 2
size_flags_horizontal = 3
[node name="TabContainer" type="TabContainer" parent="Container"]
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_yqjtg")
tab_alignment = 1
current_tab = 0
tabs_position = 1
[node name="Ship" type="Control" parent="Container/TabContainer"]
layout_mode = 2
metadata/_tab_index = 0
[node name="ShipInfo" type="VBoxContainer" parent="Container/TabContainer/Ship"]
layout_mode = 1
offset_right = 41.0
offset_bottom = 31.0
[node name="ShipInfoLabel" type="Label" parent="Container/TabContainer/Ship/ShipInfo"]
layout_mode = 2
text = "Ship Info"
[node name="Cargo" type="Control" parent="Container/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 1
[node name="Sensors" type="Control" parent="Container/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 2
[node name="Actions" type="Control" parent="Container/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 3

31
scenes/main_menu.tscn Normal file
View file

@ -0,0 +1,31 @@
[gd_scene load_steps=2 format=3 uid="uid://h3dgo6me76t7"]
[ext_resource type="Script" uid="uid://722ol864mjx4" path="res://scripts/MainMenu/MainMenuController.cs" id="1_l6cm7"]
[node name="Control" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_l6cm7")
[node name="CenterContainer" type="CenterContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
layout_mode = 2
[node name="StartGameButton" type="Button" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
text = "Start Game"
[node name="ExitGameButton" type="Button" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
text = "Exit Game"

62
scripts/AI.cs Normal file
View file

@ -0,0 +1,62 @@
using System;
public partial class AI
{
public Structure Parent { get; private set; }
private Random RandomGenerator;
public AI(Structure parent)
{
this.Parent = parent;
this.RandomGenerator = new Random();
}
public Order Think()
{
// Change of MOVE order, if mobile and in space
if (this.Parent.IsMobile && !this.Parent.IsLanded && Helpers.GetChance(30))
{
// Chance of local movement
if (Helpers.GetChance(95))
{
// Chance of aimless movement
if (Helpers.GetChance(100))
{
CoordinateVector deltaCoordinates = Helpers.GetRandomCoordinatesFromAU(
-0.5M, 0.5M,
-0.5M, 0.5M
);
CoordinateVector newCoordinates = Helpers.CalculateNewCoordinates(this.Parent, deltaCoordinates);
return new DestinationOrder(Order.OrderType.MOVE_THRUSTERS, newCoordinates);
}
else
{
}
}
else
{
// Chance of aimless movement
if (Helpers.GetChance(100))
{
CoordinateVector deltaCoordinates = Helpers.GetRandomCoordinatesFromLY(
-500M, 500M,
-500M, 500M
);
CoordinateVector newCoordinates = Helpers.CalculateNewCoordinates(this.Parent, deltaCoordinates);
return new DestinationOrder(Order.OrderType.MOVE_WARP, newCoordinates);
}
else
{
}
}
}
return new TickOrder(Order.OrderType.IDLE, 10);
}
}

1
scripts/AI.cs.uid Normal file
View file

@ -0,0 +1 @@
uid://bug3poo3pmoya

6
scripts/Constants.cs Normal file
View file

@ -0,0 +1,6 @@
public static class Constants
{
public static decimal KM_M = 1000M;
public static decimal AU_M = 149597870700M;
public static decimal LY_M = 9460737937559000M;
}

1
scripts/Constants.cs.uid Normal file
View file

@ -0,0 +1 @@
uid://docln1h1c6m41

77
scripts/Controller.cs Normal file
View file

@ -0,0 +1,77 @@
using System;
using Godot;
public partial class Controller : Node
{
private decimal LastTick = 0;
private bool TicksThrottled = false;
public Ship PlayerShip { get; private set; }
public Button ExitToMenuButton { get; private set; }
public Label ShipInfoLabel { get; private set; }
public override void _Ready()
{
base._Ready();
this.ExitToMenuButton = GetNode<Button>("Container/Top/ExitToMenuButton");
this.ExitToMenuButton.Pressed += OnExitToMenu;
this.ShipInfoLabel = GetNode<Label>("Container/TabContainer/Ship/ShipInfo/ShipInfoLabel");
CallDeferred("ReadyPlayerShip");
}
private void ReadyPlayerShip()
{
}
public void UpdatePlayerShip(Ship playerShip)
{
this.PlayerShip = playerShip;
}
public void OnTick(decimal tick, bool ticksThrottled)
{
this.LastTick = tick;
this.TicksThrottled = ticksThrottled;
CallDeferred("_OnUpdateGUI");
}
public void UpdateGUI()
{
CallDeferred("_OnUpdateGUI");
}
private void _OnUpdateGUI()
{
this.ShipInfoLabel.Text = $@"Name: {this.PlayerShip.Name}
Current Action: {this.PlayerShip.CurrentOrder?.Type.ToString() ?? "IDLE"}
Location: {this.PlayerShip.Parent.Name}
Local X: {Math.Round(Helpers.GetLocalCoordinatesX(this.PlayerShip))}
Local Y: {Math.Round(Helpers.GetLocalCoordinatesY(this.PlayerShip))}
Global X: {Math.Round(this.PlayerShip.Position.X)}
Global Y: {Math.Round(this.PlayerShip.Position.Y)}";
}
public void OnExitToMenu()
{
GetTree().ChangeSceneToFile("res://scenes/main_menu.tscn");
}
public void OnTest()
{
CoordinateVector destination = new CoordinateVector(this.PlayerShip.Position.X + Helpers.GetCoordinateFromLY(3), this.PlayerShip.Position.Y);
Order newOrder = new DestinationOrder(Order.OrderType.MOVE_WARP, destination);
this.PlayerShip.SetNewPlayerOrder(newOrder);
UpdateGUI();
}
}

View file

@ -0,0 +1 @@
uid://bladckxyu6xmy

View file

@ -0,0 +1,11 @@
public partial class DestinationOrder : Order
{
public CoordinateVector Destination { get; set; }
public DestinationOrder(OrderType type, CoordinateVector destination)
{
this.Category = OrderCategory.DESTINATION;
this.Type = type;
this.Destination = destination;
}
}

View file

@ -0,0 +1 @@
uid://cm2h2tyknkqwy

69
scripts/GameManager.cs Normal file
View file

@ -0,0 +1,69 @@
using System;
using System.Timers;
using Godot;
public partial class GameManager : Node
{
private System.Timers.Timer TickTimer;
private bool IsTickProcessing = false;
private bool IsThrottlingTicks = false;
public GameState GameState { get; private set; }
public Generator Generator { get; private set; }
public Controller Controller { get; private set; }
public Ship PlayerShip { get; private set; }
public override void _Ready()
{
base._Ready();
GeneratorSettings generatorSettings = new GeneratorSettings()
{
SpaceSize = new CoordinateVector(Helpers.GetCoordinateFromLY(5000000000), Helpers.GetCoordinateFromLY(5000000000)),
GalaxySizeMultiplier = new CoordinateVector(0.1M, 0.1M),
Galaxies = 10,
MaxNebulasPerGalaxy = 100,
MaxStarsPerGalaxy = 20000,
MaxPlanetsPerStar = 10,
MaxMoonsPerPlanet = 3,
};
this.Generator = new Generator(generatorSettings);
Universe generatedUniverse = this.Generator.GenerateUniverse();
this.GameState = new GameState();
this.GameState.New(generatedUniverse);
this.Controller = GetNode<Controller>("../");
Galaxy playerGalaxy = generatedUniverse.GameObjects[0] as Galaxy;
this.PlayerShip = this.Generator.GeneratePlayer(playerGalaxy);
playerGalaxy.GameObjects.Add(this.PlayerShip);
this.Controller.UpdatePlayerShip(this.PlayerShip);
this.TickTimer = new System.Timers.Timer(1000);
this.TickTimer.AutoReset = true;
this.TickTimer.Elapsed += OnTick;
this.TickTimer.Start();
}
private void OnTick(Object source, ElapsedEventArgs e)
{
if (this.IsTickProcessing)
{
this.IsThrottlingTicks = true;
return;
}
this.IsTickProcessing = true;
bool ticksThrottled = this.IsThrottlingTicks;
this.IsThrottlingTicks = false;
decimal currentTick = this.GameState.Universe.SimulateTick();
this.Controller.OnTick(currentTick, ticksThrottled);
this.IsTickProcessing = false;
}
}

View file

@ -0,0 +1 @@
uid://c0d47hdgdfsa6

37
scripts/GameObject.cs Normal file
View file

@ -0,0 +1,37 @@
public partial class GameObject
{
public string Name { get; private set; }
public CoordinateVector Position { get; private set; }
public CoordinateVector Size { get; private set; }
public GameObject Parent { get; private set; }
public GameObject(string name, CoordinateVector position, CoordinateVector size, GameObject parent)
{
this.Name = name;
this.Position = position;
this.Size = size;
this.Parent = parent;
}
public virtual void Simulate() { }
public void Move(CoordinateVector movementVector)
{
this.Position = Helpers.AddCoordinates(this.Position, movementVector);
}
public void MoveTo(CoordinateVector destination)
{
this.Position = destination;
}
public bool TravelTo(CoordinateVector destination, bool useWarp)
{
decimal speedAU = useWarp ? 10000 : 0.1M;
decimal speed = Helpers.GetCoordinateFromAU(speedAU);
this.Position = Helpers.CalculateMovedCoordinates(this.Position, destination, speed);
return Helpers.CompareCoordinates(this.Position, destination);
}
}

View file

@ -0,0 +1 @@
uid://cm5f76xf10ic

View file

@ -0,0 +1,22 @@
using System.Collections.Generic;
public partial class Galaxy : GameObject
{
public List<GameObject> GameObjects { get; private set; }
public Galaxy(string name, CoordinateVector position, CoordinateVector size)
: base(name, position, size, null)
{
this.GameObjects = new List<GameObject>();
}
public override void Simulate()
{
base.Simulate();
foreach (GameObject gameObject in this.GameObjects)
{
gameObject.Simulate();
}
}
}

View file

@ -0,0 +1 @@
uid://ciroqbky68llv

View file

@ -0,0 +1,13 @@
public partial class Item : GameObject
{
public Item(string name, GameObject parent)
: base(name, new CoordinateVector(0, 0), new CoordinateVector(0, 0), parent)
{
}
public override void Simulate()
{
base.Simulate();
}
}

View file

@ -0,0 +1 @@
uid://26tpqqdo7kfi

View file

@ -0,0 +1,13 @@
public partial class Component : Item
{
public Component(string name, GameObject parent)
: base(name, parent)
{
}
public override void Simulate()
{
base.Simulate();
}
}

View file

@ -0,0 +1 @@
uid://crsm66sgsoax2

View file

@ -0,0 +1,13 @@
public partial class Life : GameObject
{
public Life(string name, GameObject parent)
: base(name, new CoordinateVector(0, 0), new CoordinateVector(0, 0), parent)
{
}
public override void Simulate()
{
base.Simulate();
}
}

View file

@ -0,0 +1 @@
uid://eybn0icmypql

View file

@ -0,0 +1,22 @@
using System.Collections.Generic;
public partial class Nebula : GameObject
{
public List<GameObject> GameObjects { get; private set; }
public Nebula(string name, CoordinateVector position, CoordinateVector size, GameObject parent)
: base(name, position, size, parent)
{
this.GameObjects = new List<GameObject>();
}
public override void Simulate()
{
base.Simulate();
foreach (GameObject gameObject in this.GameObjects)
{
gameObject.Simulate();
}
}
}

View file

@ -0,0 +1 @@
uid://cyo7pd66loqvy

View file

@ -0,0 +1,35 @@
using System.Collections.Generic;
public partial class Planet : GameObject
{
public bool IsMoon { get; private set; }
public long Diameter { get; private set; }
public List<GameObject> OrbitingGameObjects { get; private set; }
public List<GameObject> PlanetGameObjects { get; private set; }
public Planet(string name, CoordinateVector position, GameObject parent, bool isMoon, long diameter)
: base(name, position, new CoordinateVector(0, 0), parent)
{
this.IsMoon = isMoon;
this.Diameter = diameter;
this.OrbitingGameObjects = new List<GameObject>();
this.PlanetGameObjects = new List<GameObject>();
}
public override void Simulate()
{
base.Simulate();
foreach (GameObject gameObject in this.OrbitingGameObjects)
{
gameObject.Simulate();
}
foreach (GameObject gameObject in this.PlanetGameObjects)
{
gameObject.Simulate();
}
}
}

View file

@ -0,0 +1 @@
uid://bgeb47vjo08xs

View file

@ -0,0 +1,23 @@
public partial class Ship : Structure
{
public Ship(string name, CoordinateVector position, GameObject parent, long diameter, bool isPlayer)
: base(name, position, parent, diameter, isPlayer)
{
this.IsMobile = true;
}
public override void Simulate()
{
base.Simulate();
if (this.IsPlayer)
{
SimulatePlayer();
}
}
protected void SimulatePlayer()
{
}
}

View file

@ -0,0 +1 @@
uid://cna2w4aqci13s

View file

@ -0,0 +1,33 @@
using System.Collections.Generic;
public partial class Star : GameObject
{
public enum SpectralClassType
{
O = 0, B = 1, A = 2, F = 3, G = 4, K = 5, M = 6
}
public SpectralClassType SpectralClass { get; private set; }
public long Diameter { get; private set; }
public List<GameObject> GameObjects { get; private set; }
public Star(string name, CoordinateVector position, GameObject parent, SpectralClassType spectralClass, long diameter)
: base(name, position, new CoordinateVector(0, 0), parent)
{
this.SpectralClass = spectralClass;
this.Diameter = diameter;
this.GameObjects = new List<GameObject>();
}
public override void Simulate()
{
base.Simulate();
foreach (GameObject gameObject in this.GameObjects)
{
gameObject.Simulate();
}
}
}

View file

@ -0,0 +1 @@
uid://clu6fkj61p62a

View file

@ -0,0 +1,136 @@
using System.Collections.Generic;
public partial class Structure : GameObject
{
public Order CurrentOrder { get; protected set; }
public bool IsPlayer { get; private set; }
public bool IsMobile { get; protected set; }
public bool IsLanded { get; protected set; }
public bool IsOrbiting { get; protected set; }
public long Diameter { get; protected set; }
public AI AI { get; protected set; }
public List<Component> Components { get; protected set; }
public List<GameObject> Cargo { get; protected set; }
public List<Life> Crew { get; protected set; }
public Structure(string name, CoordinateVector position, GameObject parent, long diameter, bool isPlayer)
: base(name, position, new CoordinateVector(0, 0), parent)
{
this.IsPlayer = isPlayer;
this.IsMobile = false;
this.IsLanded = false;
this.IsOrbiting = false;
this.Diameter = diameter;
this.AI = isPlayer ? null : new AI(this);
this.Components = new List<Component>();
this.Cargo = new List<GameObject>();
this.Crew = new List<Life>();
}
public override void Simulate()
{
base.Simulate();
foreach (GameObject component in this.Components)
{
component.Simulate();
}
foreach (GameObject cargoItem in this.Cargo)
{
cargoItem.Simulate();
}
foreach (GameObject crewMember in this.Crew)
{
crewMember.Simulate();
}
ExecuteOrder();
}
public bool SetNewPlayerOrder(Order newOrder)
{
if (!this.IsPlayer)
{
return false;
}
this.CurrentOrder = newOrder;
return true;
}
protected bool ExecuteOrder()
{
bool finished = false;
if (this.CurrentOrder == null)
{
if (!this.IsPlayer && this.AI != null)
{
this.CurrentOrder = this.AI.Think();
}
return false;
}
if (this.CurrentOrder.Category == Order.OrderCategory.TICK)
{
finished = ExecuteTickOrder(this.CurrentOrder as TickOrder);
}
if (this.CurrentOrder.Category == Order.OrderCategory.DESTINATION)
{
finished = ExecuteDestinationOrder(this.CurrentOrder as DestinationOrder);
}
if (finished)
{
this.CurrentOrder = null;
}
return finished;
}
protected bool ExecuteTickOrder(TickOrder tickOrder)
{
bool finished = false;
switch (tickOrder.Type)
{
case Order.OrderType.IDLE:
break;
case Order.OrderType.ORBIT:
break;
case Order.OrderType.LAND:
break;
}
return finished;
}
protected bool ExecuteDestinationOrder(DestinationOrder destinationOrder)
{
bool finished = false;
switch (destinationOrder.Type)
{
case Order.OrderType.MOVE_THRUSTERS:
finished = this.TravelTo(destinationOrder.Destination, false);
break;
case Order.OrderType.MOVE_WARP:
finished = this.TravelTo(destinationOrder.Destination, true);
break;
}
return finished;
}
}

View file

@ -0,0 +1 @@
uid://jpr7mwxec56

View file

@ -0,0 +1,39 @@
using System.Collections.Generic;
using System.Threading.Tasks;
public partial class Universe
{
public decimal CurrentTick { get; private set; }
public List<GameObject> GameObjects { get; private set; }
public Ship PlayerShip { get; private set; }
public Universe()
{
this.GameObjects = new List<GameObject>();
}
public decimal SimulateTick()
{
this.CurrentTick++;
List<Task> galaxySimulationTasks = new List<Task>();
foreach (GameObject gameObject in this.GameObjects)
{
if (gameObject.GetType().Name == "Galaxy")
{
Task galaxySimulation = new Task(() => gameObject.Simulate());
galaxySimulation.Start();
galaxySimulationTasks.Add(galaxySimulation);
continue;
}
gameObject.Simulate();
}
Task.WaitAll(galaxySimulationTasks.ToArray());
return this.CurrentTick;
}
}

View file

@ -0,0 +1 @@
uid://bwhcw860ysbpm

21
scripts/GameState.cs Normal file
View file

@ -0,0 +1,21 @@
using System;
public partial class GameState
{
public Universe Universe { get; private set; }
public void New(Universe newUniverse)
{
this.Universe = newUniverse;
}
public void Load()
{
throw new NotImplementedException();
}
public void Save()
{
throw new NotImplementedException();
}
}

1
scripts/GameState.cs.uid Normal file
View file

@ -0,0 +1 @@
uid://x55fwr7o2hkc

188
scripts/Generator.cs Normal file
View file

@ -0,0 +1,188 @@
using System;
using System.Threading.Tasks;
public struct GeneratorSettings
{
public CoordinateVector SpaceSize;
public CoordinateVector GalaxySizeMultiplier;
public long Galaxies;
public long MaxNebulasPerGalaxy;
public long MaxStarsPerGalaxy;
public long MaxPlanetsPerStar;
public long MaxMoonsPerPlanet;
}
public partial class Generator
{
private GeneratorSettings GeneratorSettings;
private Random RandomGenerator;
public Generator(GeneratorSettings generatorSettings)
{
this.GeneratorSettings = generatorSettings;
this.RandomGenerator = new Random();
}
public Universe GenerateUniverse()
{
Universe universe = new Universe();
Task[] galaxyGenerationTasks = new Task[this.GeneratorSettings.Galaxies];
for (long i = 0; i < this.GeneratorSettings.Galaxies; i++)
{
galaxyGenerationTasks[i] = new Task(() =>
{
Galaxy galaxy = GenerateGalaxy("Galaxy " + i);
GenerateLife(galaxy);
universe.GameObjects.Add(galaxy);
});
galaxyGenerationTasks[i].Start();
}
Task.WaitAll(galaxyGenerationTasks);
return universe;
}
public Galaxy GenerateGalaxy(string name)
{
CoordinateVector galaxyPosition = Helpers.GetRandomCoordinates(
0M, this.GeneratorSettings.SpaceSize.X,
0M, this.GeneratorSettings.SpaceSize.Y
);
CoordinateVector galaxySize = Helpers.GetRandomCoordinatesFromLY(
50000, 250000,
50000, 250000,
this.GeneratorSettings.GalaxySizeMultiplier.X
);
Galaxy galaxy = new Galaxy(name, galaxyPosition, galaxySize);
long nebulaCount = Helpers.GetRandomNumber(0, this.GeneratorSettings.MaxNebulasPerGalaxy);
long starCount = Helpers.GetRandomNumber(10000, this.GeneratorSettings.MaxStarsPerGalaxy);
for (long i = 0; i < nebulaCount; i++)
{
Nebula nebula = GenerateNebula(name + ", Nebula " + i, galaxy);
galaxy.GameObjects.Add(nebula);
}
for (long i = 0; i < starCount; i++)
{
Star star = GenerateStar(name + ", Star " + i, galaxy);
galaxy.GameObjects.Add(star);
}
return galaxy;
}
public Nebula GenerateNebula(string name, GameObject parent)
{
CoordinateVector nebulaPosition = Helpers.GetRandomCoordinates(
parent.Position.X, parent.Position.X + parent.Size.X,
parent.Position.Y, parent.Position.Y + parent.Size.Y
);
CoordinateVector nebulaSize = Helpers.GetRandomCoordinatesFromLY(
1, 100,
1, 100
);
Nebula nebula = new Nebula(name, nebulaPosition, nebulaSize, parent);
decimal nebulaAreaLY = Helpers.GetCoordinateInLY(nebulaSize.X) * Helpers.GetCoordinateInLY(nebulaSize.Y);
long starCount = Helpers.GetRandomNumber(1, (long)(Math.Sqrt((double)nebulaAreaLY) * 2));
for (long i = 0; i < starCount; i++)
{
Star star = GenerateStar(name + ", Star " + i, nebula);
nebula.GameObjects.Add(star);
}
return nebula;
}
public Star GenerateStar(string name, GameObject parent)
{
CoordinateVector starPosition = Helpers.GetRandomCoordinates(
parent.Position.X, parent.Position.X + parent.Size.X,
parent.Position.Y, parent.Position.Y + parent.Size.Y
);
Star.SpectralClassType starSpectralClass = (Star.SpectralClassType)(this.RandomGenerator.Next() % 7);
long starDiameter = Helpers.GetRandomNumber(1000000, 100000000000);
Star star = new Star(name, starPosition, parent, starSpectralClass, starDiameter);
long planetCount = Helpers.GetRandomNumber(0, this.GeneratorSettings.MaxPlanetsPerStar);
for (long i = 0; i < planetCount; i++)
{
Planet planet = GeneratePlanet(name + " - " + i, star);
star.GameObjects.Add(planet);
}
return star;
}
public Planet GeneratePlanet(string name, GameObject parent)
{
decimal offset = Helpers.GetCoordinateFromAU(10);
CoordinateVector planetPosition = Helpers.GetRandomCoordinates(
parent.Position.X - offset, parent.Position.X + offset,
parent.Position.Y - offset, parent.Position.Y + offset
);
long planetDiameter = Helpers.GetRandomNumber(1000, 10000);
Planet planet = new Planet(name, planetPosition, parent, false, planetDiameter);
long moonCount = Helpers.GetRandomNumber(0, this.GeneratorSettings.MaxMoonsPerPlanet);
for (long i = 0; i < moonCount; i++)
{
Planet moon = GenerateMoon(name + " (" + i + ")", planet, planetDiameter);
planet.OrbitingGameObjects.Add(moon);
}
return planet;
}
public Planet GenerateMoon(string name, GameObject parent, long parentDiameter)
{
decimal offset = Helpers.GetCoordinateFromKM(1000);
CoordinateVector moonPosition = Helpers.GetRandomCoordinates(
parent.Position.X - offset, parent.Position.X + offset,
parent.Position.Y - offset, parent.Position.Y + offset
);
long moonDiameter = Helpers.GetRandomNumber(100, (parentDiameter / 2));
Planet planet = new Planet(name, moonPosition, parent, true, moonDiameter);
return planet;
}
public void GenerateLife(Galaxy galaxy)
{
}
public Ship GeneratePlayer(GameObject parent)
{
decimal positionX = Helpers.GetRandomCoordinate(parent.Position.X, parent.Size.X, 1);
decimal positionY = Helpers.GetRandomCoordinate(parent.Position.Y, parent.Size.Y, 1);
Ship playerShip = new Ship(
"Player",
new CoordinateVector(positionX, positionY),
parent,
20,
true
);
return playerShip;
}
}

1
scripts/Generator.cs.uid Normal file
View file

@ -0,0 +1 @@
uid://bhfo1kn5638o1

234
scripts/Helpers.cs Normal file
View file

@ -0,0 +1,234 @@
using System;
public static partial class Helpers
{
public static Random RNG = new Random();
public static bool GetChance(float percentage)
{
return RNG.NextSingle() < percentage / 100;
}
public static long GetRandomNumber(long min, long max)
{
return RNG.NextInt64(min, max);
}
public static double GetRandomNumber(double min, double max)
{
double diff = max - min;
return RNG.NextDouble() * diff + min;
}
public static decimal GetRandomNumber(decimal min, decimal max)
{
decimal diff = max - min;
return (decimal)RNG.NextDouble() * diff + min;
}
public static int[] GetDeconstructedDecimal(decimal value)
{
return decimal.GetBits(value);
}
public static decimal GetConstructedDecimal(int[] bits)
{
return new decimal(bits);
}
public static decimal GetCoordinateFromKM(decimal coordinate)
{
return coordinate * Constants.KM_M;
}
public static decimal GetCoordinateFromAU(decimal coordinate)
{
return coordinate * Constants.AU_M;
}
public static decimal GetCoordinateFromLY(decimal coordinate)
{
return coordinate * Constants.LY_M;
}
public static decimal GetCoordinateInKM(decimal coordinate)
{
return coordinate / Constants.KM_M;
}
public static decimal GetCoordinateInAU(decimal coordinate)
{
return coordinate / Constants.AU_M;
}
public static decimal GetCoordinateInLY(decimal coordinate)
{
return coordinate / Constants.LY_M;
}
public static decimal GetRandomCoordinate(decimal min, decimal max, decimal multiplier = 1)
{
decimal diff = max - min;
return GetRandomNumber(min, max) * multiplier;
}
public static decimal GetRandomCoordinateFromKM(decimal min, decimal max, decimal multiplier = 1)
{
return GetRandomCoordinate(min, max, multiplier * Constants.KM_M);
}
public static decimal GetRandomCoordinateFromAU(decimal min, decimal max, decimal multiplier = 1)
{
return GetRandomCoordinate(min, max, multiplier * Constants.AU_M);
}
public static decimal GetRandomCoordinateFromLY(decimal min, decimal max, decimal multiplier = 1)
{
return GetRandomCoordinate(min, max, multiplier * Constants.LY_M);
}
public static CoordinateVector GetRandomCoordinates(decimal minX, decimal maxX, decimal minY, decimal maxY, decimal multiplier = 1)
{
decimal diffX = maxX - minX;
decimal diffY = maxY - minY;
decimal coordinateX = GetRandomCoordinate(minX, maxX, multiplier);
decimal coordinateY = GetRandomCoordinate(minY, maxY, multiplier);
return new CoordinateVector(coordinateX, coordinateY);
}
public static CoordinateVector GetRandomCoordinatesFromKM(decimal minX, decimal maxX, decimal minY, decimal maxY, decimal multiplier = 1)
{
return GetRandomCoordinates(minX, maxX, minY, maxY, multiplier * Constants.KM_M);
}
public static CoordinateVector GetRandomCoordinatesFromAU(decimal minX, decimal maxX, decimal minY, decimal maxY, decimal multiplier = 1)
{
return GetRandomCoordinates(minX, maxX, minY, maxY, multiplier * Constants.AU_M);
}
public static CoordinateVector GetRandomCoordinatesFromLY(decimal minX, decimal maxX, decimal minY, decimal maxY, decimal multiplier = 1)
{
return GetRandomCoordinates(minX, maxX, minY, maxY, multiplier * Constants.LY_M);
}
public static double CalculateDistance(CoordinateVector coordinates1, CoordinateVector coordinates2)
{
CoordinateVector delta = CalculateDeltaCoordinates(coordinates1, coordinates2);
return Math.Sqrt(
Math.Pow((double)delta.X, 2) +
Math.Pow((double)delta.Y, 2)
);
}
public static double CalculateDistance(Structure structure1, Structure structure2)
{
return CalculateDistance(structure1.Position, structure2.Position);
}
public static CoordinateVector AddCoordinates(CoordinateVector coordinates1, CoordinateVector coordinates2)
{
return new CoordinateVector(coordinates1.X + coordinates2.X, coordinates1.Y + coordinates2.Y);
}
public static CoordinateVector SubtractCoordinates(CoordinateVector coordinates1, CoordinateVector coordinates2)
{
return new CoordinateVector(coordinates1.X - coordinates2.X, coordinates1.Y - coordinates2.Y);
}
public static CoordinateVector MultiplyCoordinates(CoordinateVector coordinates1, CoordinateVector coordinates2)
{
return new CoordinateVector(coordinates1.X * coordinates2.X, coordinates1.Y * coordinates2.Y);
}
public static CoordinateVector DivideCoordinates(CoordinateVector coordinates1, CoordinateVector coordinates2)
{
return new CoordinateVector(coordinates1.X / coordinates2.X, coordinates1.Y / coordinates2.Y);
}
public static bool CompareCoordinates(CoordinateVector coordinates1, CoordinateVector coordinates2)
{
if (coordinates1.X != coordinates2.X)
{
return false;
}
if (coordinates1.Y != coordinates2.Y)
{
return false;
}
return true;
}
public static CoordinateVector CalculateDeltaCoordinates(CoordinateVector coordinates1, CoordinateVector coordinates2)
{
decimal diffX = Math.Abs(coordinates1.X - coordinates2.X);
decimal diffY = Math.Abs(coordinates1.Y - coordinates2.Y);
return new CoordinateVector(diffX, diffY);
}
public static CoordinateVector CalculateDeltaCoordinates(Structure structure, CoordinateVector coordinates)
{
return CalculateDeltaCoordinates(structure.Position, coordinates);
}
public static CoordinateVector CalculateNewCoordinates(CoordinateVector coordinates1, CoordinateVector coordinates2)
{
decimal diffX = coordinates1.X + coordinates2.X;
decimal diffY = coordinates1.Y + coordinates2.Y;
return new CoordinateVector(diffX, diffY);
}
public static CoordinateVector CalculateNewCoordinates(Structure structure, CoordinateVector deltaCoordinates)
{
return CalculateNewCoordinates(structure.Position, deltaCoordinates);
}
public static CoordinateVector CalculateMoveCoordinates(CoordinateVector startCoordinates, CoordinateVector endCoordinates, decimal speed)
{
decimal distance = (decimal)CalculateDistance(startCoordinates, endCoordinates);
if (speed >= distance)
{
return SubtractCoordinates(endCoordinates, startCoordinates);
}
CoordinateVector deltaCoordinates = CalculateDeltaCoordinates(startCoordinates, endCoordinates);
decimal fractionCrossed = speed / distance;
decimal moveCoordinateX = deltaCoordinates.X * fractionCrossed;
decimal moveCoordinateY = deltaCoordinates.Y * fractionCrossed;
return new CoordinateVector(moveCoordinateX, moveCoordinateY);
}
public static CoordinateVector CalculateMovedCoordinates(CoordinateVector startCoordinates, CoordinateVector endCoordinates, decimal speed)
{
CoordinateVector moveCoordinates = CalculateMoveCoordinates(startCoordinates, endCoordinates, speed);
return AddCoordinates(startCoordinates, moveCoordinates);
}
public static decimal GetLocalCoordinatesX(GameObject target)
{
return target.Position.X - target.Parent.Position.X;
}
public static decimal GetLocalCoordinatesY(GameObject target)
{
return target.Position.Y - target.Parent.Position.Y;
}
public static CoordinateVector GetLocalCoordinates(GameObject target)
{
return SubtractCoordinates(target.Position, target.Parent.Position);
}
}

1
scripts/Helpers.cs.uid Normal file
View file

@ -0,0 +1 @@
uid://c4035gn5cnowt

View file

@ -0,0 +1,28 @@
using Godot;
public partial class MainMenuController : Node
{
public Button StartGameButton { get; private set; }
public Button ExitGameButton { get; private set; }
public override void _Ready()
{
base._Ready();
this.StartGameButton = GetNode<Button>("CenterContainer/VBoxContainer/StartGameButton");
this.ExitGameButton = GetNode<Button>("CenterContainer/VBoxContainer/ExitGameButton");
this.StartGameButton.Pressed += OnStartGame;
this.ExitGameButton.Pressed += OnExitGame;
}
public void OnStartGame()
{
GetTree().ChangeSceneToFile("res://scenes/game.tscn");
}
public void OnExitGame()
{
GetTree().Quit();
}
}

View file

@ -0,0 +1 @@
uid://722ol864mjx4

21
scripts/Order.cs Normal file
View file

@ -0,0 +1,21 @@
public abstract class Order
{
public enum OrderCategory
{
TICK,
DESTINATION,
}
public enum OrderType
{
IDLE,
MOVE_THRUSTERS, MOVE_WARP,
ENTER_GALAXY, EXIT_GALAXY,
ENTER_NEBULA, EXIT_NEBULA,
ENTER_SYSTEM, EXIT_SYSTEM,
ORBIT, LEAVE_ORBIT,
LAND, TAKE_OFF,
}
public OrderCategory Category { get; protected set; }
public OrderType Type { get; protected set; }
}

1
scripts/Order.cs.uid Normal file
View file

@ -0,0 +1 @@
uid://bu1hwijrat3ky

View file

@ -0,0 +1,11 @@
public struct CoordinateVector
{
public decimal X { get; set; }
public decimal Y { get; set; }
public CoordinateVector(decimal x, decimal y)
{
this.X = x;
this.Y = y;
}
}

View file

@ -0,0 +1 @@
uid://dyyngkletu8nj

11
scripts/TickOrder.cs Normal file
View file

@ -0,0 +1,11 @@
public partial class TickOrder : Order
{
public long Ticks { get; set; }
public TickOrder(OrderType type, long ticks)
{
this.Category = OrderCategory.TICK;
this.Type = type;
this.Ticks = ticks;
}
}

1
scripts/TickOrder.cs.uid Normal file
View file

@ -0,0 +1 @@
uid://b333gr3hrykkk