diff --git a/Assets/Planet.cs b/Assets/Planet.cs index 568a13b..4873205 100644 --- a/Assets/Planet.cs +++ b/Assets/Planet.cs @@ -4,6 +4,7 @@ using UnityEngine; using DataStructures.ViliWonka.KDTree; using System; using System.Text; +using UnityEditor.Search; public class Planet : MonoBehaviour { @@ -11,6 +12,7 @@ public class Planet : MonoBehaviour private LineRenderer _lineRenderer; private CircleCollider2D _circleCollider; private Network _network; + public KDQuery Query => _query; private KDQuery _query; public KDTree Tree => _tree; private KDTree _tree; @@ -35,10 +37,8 @@ public class Planet : MonoBehaviour void Start() { - while (_units.Count < 10) + while (_units.Count < 16) SpawnUnit(); - - InvokeRepeating("ChangeUnits", 0.0f, 1f); } void OnMouseDown() @@ -53,9 +53,9 @@ public class Planet : MonoBehaviour return (Vector2)transform.position + new Vector2(Mathf.Cos(theta), Mathf.Sin(theta)) * radius; } - public float GetUnitAngle(Unit unit) + public float GetAngle(Vector2 position) { - var angle = Mathf.Atan2(unit.transform.position.y, unit.transform.position.x) * Mathf.Rad2Deg; + var angle = Mathf.Atan2(position.y - transform.position.y, position.x - transform.position.x) * Mathf.Rad2Deg; return angle < 0 ? angle + 360 : angle; } diff --git a/Assets/BasePlanet.prefab b/Assets/Resources/BasePlanet.prefab similarity index 100% rename from Assets/BasePlanet.prefab rename to Assets/Resources/BasePlanet.prefab diff --git a/Assets/BasePlanet.prefab.meta b/Assets/Resources/BasePlanet.prefab.meta similarity index 100% rename from Assets/BasePlanet.prefab.meta rename to Assets/Resources/BasePlanet.prefab.meta diff --git a/Assets/Unit.cs b/Assets/Unit.cs index 28df5df..b574137 100644 --- a/Assets/Unit.cs +++ b/Assets/Unit.cs @@ -1,74 +1,145 @@ using System; +using System.Collections.Generic; using System.Linq; using UnityEngine; +using Quaternion = UnityEngine.Quaternion; using Random = UnityEngine.Random; +using Vector2 = UnityEngine.Vector2; +using Vector3 = UnityEngine.Vector3; public class Unit : MonoBehaviour { private Planet planet; - private Vector2 planetaryVelocity; // X: rotational, Y: altitude public float edgeWidth; public Color fillColor = Color.white; public Color edgeColor = Color.white; public float Size; public int TreeIndex; - private float RotationSpeed; - private float BobbingOffset; + private Vector2 _velocity = Vector3.up; + private float timeOffset; void Start() { Render(); + _velocity = Random.insideUnitCircle.normalized; planet = GetComponentInParent(); - planetaryVelocity = new Vector2(0, 0) - { - x = (Random.value > 0.5f ? 1 : -1) * 32 * Random.Range(0.8f, 1.2f), - }; - RotationSpeed = Random.value > 0.5f ? 1 : -1 * Random.Range(0.8f, 1.2f) * 4f; - BobbingOffset = Random.Range(0, (float)(2 * Math.PI)); + timeOffset = Random.Range(0, (float)(2 * Math.PI)); + } + + private Vector2 SteerTowards(Vector2 vector) + { + Vector2 v = vector.normalized * 1 - _velocity; + var clamped = Vector2.ClampMagnitude(v, 1); + Debug.Log($"SteerTowards {planet.name}/{name} Vector: {vector}, Modified Vector: {v}, Cur Velocity: {_velocity}, Clamped Vector: {clamped}"); + return clamped; } void Update() { - // Rotate itself slightly - transform.Rotate(new Vector3(0, 0, Time.deltaTime * RotationSpeed)); + var acceleration = Vector2.zero; - transform.Translate(Vector3.up * Time.deltaTime); + // var upcomingAngle = planet.GetAngle(transform.position + (Vector3)_velocity); + // var angleTarget = planet.GetSurfacePosition(upcomingAngle, 0.4f); + // acceleration -= angleTarget; - // Get distance from planet + var targetDistance = (Mathf.Sin(Time.time * 0.5f + timeOffset) + 1) / 2f; + var surfaceTarget = planet.GetSurfacePosition(planet.GetAngle((Vector2)transform.position + _velocity), targetDistance); + var surfaceTargetVector = ((Vector2)transform.position - surfaceTarget).normalized; var distance = Vector2.Distance(transform.position, planet.transform.position) - planet.Size / 100f; - var maxDistance = 1f; - var minDistance = 0.2f; + // var vectorMultiplier = Mathf.LerpUnclamped(1f, 1.5f, 2f * Math.Abs(targetDistance - distance) / targetDistance); + // var vectorMultiplier = Mathf.LerpUnclamped(0.5f, 1f, distance < targetDistance ? 0.3f / distance : distance / 0.2f); + surfaceTargetVector *= 1.5f; + acceleration -= surfaceTargetVector; - bool isTooFar = distance > maxDistance; - bool isTooClose = distance < minDistance; - - // If incorrect distance, rotate - if (isTooFar || isTooClose) + if (TreeIndex == 0) { - var directionToPlanet = (planet.transform.position - transform.position).normalized; - var projectionOnRight = Vector3.Dot(directionToPlanet, transform.right); - var planetOnRight = projectionOnRight < 0; - - var direction = planetOnRight == isTooFar ? 1 : -1; - var turningSpeed = 200f; - if (isTooClose) turningSpeed *= 3; - else if (isTooFar) turningSpeed *= (distance - maxDistance); - transform.Rotate(new Vector3(0, 0, direction * turningSpeed * Time.deltaTime)); - - // var angle = Mathf.Atan2(transform.position.y, transform.position.x) * Mathf.Rad2Deg; - // angle += Random.Range(-10, 10); - // transform.rotation = Quaternion.Euler(0, 0, angle); + Debug.Log($"{planet.name} Acceleration: {acceleration}, Velocity: {_velocity}"); } + Vector2 newVelocity = _velocity + acceleration * Time.deltaTime; + float speed = newVelocity.magnitude; + Vector2 dir = newVelocity / speed; + speed = Mathf.Clamp(speed, 0.5f, 1.5f); + _velocity = dir * speed; + + var results = new List(); + planet.Query.Radius(planet.Tree, transform.position, 0.1f, results); + Vector2 away = Vector2.zero; + foreach (var unitIndex in results) + { + if (unitIndex == TreeIndex) continue; + var diff = (Vector2)(planet.Tree.Points[unitIndex] - transform.position); + away -= diff.normalized; + } + acceleration += away * 0.5f; + + transform.eulerAngles = new Vector3(0, 0, Mathf.Rad2Deg * -Mathf.Atan2(_velocity.x, _velocity.y)); + transform.position += (Vector3)_velocity * Time.deltaTime; planet.Tree.Points[TreeIndex] = transform.position; + + // var angle = planet.GetAngle(transform.position); + // var forwardAngle = planet.GetAngle(transform.forward); + + // Get distance from planet + // var distance = Vector2.Distance(transform.position, planet.transform.position) - planet.Size / 100f; + // var maxDistance = 1f; + // var minDistance = 0.2f; + + // bool isTooFar = distance > maxDistance; + // bool isTooClose = distance < minDistance; + + // var steerTarget = Vector3.zero; + + // If incorrect distance, rotate + // if (isTooFar || isTooClose) + // { + // var directionToPlanet = (planet.transform.position - transform.position).normalized; + // var projectionOnRight = Vector3.Dot(directionToPlanet, transform.right); + // var planetOnRight = projectionOnRight < 0; + + // steerTarget = planetOnRight ? transform.right : -transform.right; + + // var direction = planetOnRight == isTooFar ? 1 : -1; + // var turningSpeed = 200f; + // if (isTooClose) turningSpeed *= 3; + // else if (isTooFar) turningSpeed *= (distance - maxDistance); + // transform.Rotate(new Vector3(0, 0, direction * turningSpeed * Time.deltaTime)); + + // if (steerTarget == Vector3.zero) + // steerTarget = transform.up; + + + // var angle = new Vector3(0, 0, Mathf.Rad2Deg * -Mathf.Atan2(steerTarget.x, steerTarget.y)); + // transform.eulerAngles = Vector3.Lerp(transform.eulerAngles, angle, Time.deltaTime * 2f); + + // transform.position += transform.up * Time.deltaTime; } public void OnDrawGizmos() { - // Draw a line forward - Gizmos.color = Color.red; - Gizmos.DrawLine(transform.position, transform.position + transform.up); + var surfaceTarget = planet.GetSurfacePosition(planet.GetAngle((Vector2)transform.position + _velocity), 0.4f); + Gizmos.color = Color.blue; + Gizmos.DrawLine(transform.position, surfaceTarget); + + var velocityPosition = transform.position + (Vector3)_velocity; + Gizmos.color = Color.green; + Gizmos.DrawLine(transform.position, velocityPosition); + + // Draw the angle from the planet center to the unit + // var angle = planet.GetAngle(transform.position); + // // Draw the angle from the unit's immediate forward to the planet center + // var forwardAngle = planet.GetAngle(transform.position - transform.up); + // var distance = Vector2.Distance(transform.position, planet.transform.position) - planet.Size / 100f; + + // Gizmos.color = Color.red; + // Gizmos.DrawLine(planet.transform.position, planet.GetSurfacePosition(angle, distance)); + // Gizmos.color = Color.green; + // Gizmos.DrawLine(planet.transform.position, planet.GetSurfacePosition(forwardAngle, distance)); + + // // Draw a line forward + // Gizmos.color = Color.red; + // Gizmos.DrawLine(transform.position, transform.position + transform.up); } private void OnDestroy() @@ -131,4 +202,6 @@ public class Unit : MonoBehaviour lineRenderer.positionCount = mesh.vertices.Length; lineRenderer.SetPositions(mesh.vertices); } + + } \ No newline at end of file diff --git a/README.md b/README.md index 3bf14b6..e3f2de6 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,18 @@ A simple puzzle game about growth. - Scroll to lower/raise the total percentage of units. - Drag to another planet, release to send units. - Until units arrive, they won't be selectable or part of the usable population on a planet. + +## Planet Selection + +1. Click on a Planet +2. Planet emits signal to Network +3. Network pulls Selection GameObject into view, overhead planet +4. Network takes all scroll key inputs, re-renders Selection gameobject to fit percentage +5. Click on another planet (to send units), or same one (to cancel) +6. Network sends signal to Planet to send units +7. Or if cancelled, Selection gameObject is hidden +8. If sent, Planet tells units to start moving to another planet + +## Unit Combat + +All units are placed inside datastructure