Aetheria/Assets/Scripts/ZoneGeneratorTest.cs
hyperion51 fd92c80876 Blueprints & Resources
Added the ability to associate simple commodities with resource maps
Added resource placement to zone generator
Added crafting blueprints and stat addressing system
Refactored Thrusters and Shields into Behaviors
Fixed server losing database connection
Updated icons
2020-04-09 07:48:45 +01:00

159 lines
6.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Mathematics;
using UnityEngine;
using static Unity.Mathematics.math;
using Random = UnityEngine.Random;
public class ZoneGeneratorTest : MonoBehaviour
{
public Galaxy Galaxy;
public MeshRenderer ZoneBackground;
public MeshRenderer ZoneBoundary;
public ZoneObject ZoneObjectPrefab;
public ParticleSystem BeltPrefab;
public Texture2D PlanetSprite;
public Texture2D GasGiantSprite;
public Texture2D SunSprite;
public float ZoneSizeScale = .01f;
public float ZoneMassScale = .5f;
public float ZoneMassPower = .33f;
public float ZoneOrbitSpeed = 10;
private DatabaseCache _cache;
private Dictionary<Guid, ZoneObject> _zoneObjects = new Dictionary<Guid, ZoneObject>();
private Dictionary<Guid, ParticleSystem> _zoneBelts = new Dictionary<Guid, ParticleSystem>();
private List<ZoneObject> _wormholes = new List<ZoneObject>();
private Dictionary<Guid, float2> _orbitPositions = new Dictionary<Guid, float2>();
private GameContext _context;
private Material _boundaryMaterial;
// Determine orbital position recursively, caching parent positions to avoid repeated calculations
private float2 GetOrbitPosition(Guid orbit)
{
// Root orbit is fixed at center
if(orbit==Guid.Empty)
return Unity.Mathematics.float2.zero;
if (!_orbitPositions.ContainsKey(orbit))
{
var orbitData = _cache.Get<OrbitData>(orbit);
_orbitPositions[orbit] = GetOrbitPosition(orbitData.Parent) + (orbitData.Period < .01f ? Unity.Mathematics.float2.zero :
OrbitData.Evaluate(Time.time * ZoneOrbitSpeed / -orbitData.Period + orbitData.Phase) *
orbitData.Distance);
}
var position = _orbitPositions[orbit];
if (float.IsNaN(position.x))
{
Debug.Log("Orbit position is NaN, something went very wrong!");
return Unity.Mathematics.float2.zero;
}
return _orbitPositions[orbit];
}
void Start()
{
_cache = new DatabaseCache();
_context = new GameContext(_cache, Debug.Log);
_boundaryMaterial = ZoneBoundary.material;
}
void Update()
{
_orbitPositions.Clear();
foreach (var planet in _zoneObjects)
{
var planetData = _cache.Get<PlanetData>(planet.Key);
planet.Value.transform.position = (Vector2) GetOrbitPosition(planetData.Orbit) * ZoneSizeScale;
}
foreach (var belt in _zoneBelts)
{
var planetData = _cache.Get<PlanetData>(belt.Key);
belt.Value.transform.position = float3(GetOrbitPosition(_cache.Get<OrbitData>(planetData.Orbit).Parent) * ZoneSizeScale, .15f);
}
if (Input.GetKeyDown(KeyCode.Space))
{
PopulateZone();
}
}
void PopulateZone()
{
// Delete all the existing zone contents
foreach (var zoneObject in _zoneObjects.Values) Destroy(zoneObject.gameObject);//zoneObject.GetComponent<Prototype>().ReturnToPool();
_zoneObjects.Clear();
foreach (var zoneObject in _wormholes) Destroy(zoneObject.gameObject); //zoneObject.GetComponent<Prototype>().ReturnToPool();
_wormholes.Clear();
foreach (var belt in _zoneBelts.Values) Destroy(belt.gameObject);
_zoneBelts.Clear();
float2 position;
do
{
position = float2(Random.value, Random.value);
} while (Galaxy.MapData.StarDensity.Evaluate(position, Galaxy.MapData.GlobalData) < .1f);
var zone = new ZoneData{Context = _context, Name = Guid.NewGuid().ToString(), Position = position};
OrbitData[] orbits;
PlanetData[] planets;
ZoneGenerator.GenerateZone(
global: Galaxy.MapData.GlobalData,
zone: zone,
mapLayers: Galaxy.MapData.ResourceDensities,
resources: Array.Empty<SimpleCommodityData>(),
orbitData: out orbits,
planetsData: out planets);
_cache.AddAll(orbits);
_cache.AddAll(planets);
_cache.Add(zone);
float zoneDepth = 0;
foreach (var planet in planets)
{
if (!planet.Belt)
{
var planetObject = Instantiate(ZoneObjectPrefab, transform);
_zoneObjects[planet.ID] = planetObject;
planetObject.Label.text = planet.Name;
planetObject.GravityMesh.gameObject.SetActive(true);
planetObject.GravityMesh.transform.localScale =
Vector3.one * (pow(planet.Mass, Galaxy.MapData.GlobalData.GravityRadiusExponent) *
Galaxy.MapData.GlobalData.GravityRadiusMultiplier * 2 * ZoneSizeScale);
var depth = pow(planet.Mass, ZoneMassPower) * ZoneMassScale;
if (depth > zoneDepth)
zoneDepth = depth;
planetObject.GravityMesh.material.SetFloat("_Depth", depth);
planetObject.Icon.material.SetTexture("_MainTex",
planet.Mass > Galaxy.MapData.GlobalData.SunMass ? SunSprite :
planet.Mass > Galaxy.MapData.GlobalData.GasGiantMass ? GasGiantSprite :
PlanetSprite);
}
else
{
var beltObject = Instantiate(BeltPrefab, transform);
_zoneBelts[planet.ID] = beltObject;
var orbit = _cache.Get<OrbitData>(planet.Orbit);
var beltEmission = beltObject.emission;
beltEmission.rateOverTime = new ParticleSystem.MinMaxCurve(pow(planet.Mass,Galaxy.MapData.GlobalData.BeltMassExponent) / Galaxy.MapData.GlobalData.BeltMassRatio * orbit.Distance);
var beltShape = beltObject.shape;
beltShape.radius = orbit.Distance * ZoneSizeScale;
beltShape.donutRadius = orbit.Distance * ZoneSizeScale / 2;
var beltVelocity = beltObject.velocityOverLifetime;
beltVelocity.orbitalZ = orbit.Distance * ZoneSizeScale / orbit.Period * ZoneOrbitSpeed;
beltObject.Simulate(60);
beltObject.Play();
}
}
var zoneRadius = (zone.Radius * ZoneSizeScale * 2);
ZoneBackground.material.SetFloat("_ClipDistance", zoneRadius);
ZoneBackground.material.SetFloat("_HeightRange", zoneDepth + _boundaryMaterial.GetFloat("_Depth"));
ZoneBoundary.transform.localScale = Vector3.one * zoneRadius;
}
}