diff --git a/Assets/Scenes/RopeTest.unity b/Assets/Scenes/RopeTest.unity index ffb2742..ccd865a 100644 --- a/Assets/Scenes/RopeTest.unity +++ b/Assets/Scenes/RopeTest.unity @@ -135,6 +135,7 @@ GameObject: - component: {fileID: 347555805} - component: {fileID: 347555804} - component: {fileID: 347555803} + - component: {fileID: 347555807} m_Layer: 0 m_Name: EnemyTest (3) m_TagString: Untagged @@ -271,6 +272,39 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &347555807 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 347555802} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1fdfc885f1a69704b893825cf9e616ba, type: 3} + m_Name: + m_EditorClassIdentifier: + maxHealth: 100 + OnHealthZero: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 347555807} + m_TargetAssemblyTypeName: HealthComponent, Assembly-CSharp + m_MethodName: SimpleKill + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + OnHealthChange: + m_PersistentCalls: + m_Calls: [] + minThreshold: 1 + squezeDamageScalor: 1 --- !u!1 &418427021 GameObject: m_ObjectHideFlags: 0 @@ -283,6 +317,7 @@ GameObject: - component: {fileID: 418427024} - component: {fileID: 418427023} - component: {fileID: 418427022} + - component: {fileID: 418427026} m_Layer: 0 m_Name: EnemyTest (4) m_TagString: Untagged @@ -419,6 +454,39 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &418427026 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 418427021} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1fdfc885f1a69704b893825cf9e616ba, type: 3} + m_Name: + m_EditorClassIdentifier: + maxHealth: 100 + OnHealthZero: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 418427026} + m_TargetAssemblyTypeName: HealthComponent, Assembly-CSharp + m_MethodName: SimpleKill + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + OnHealthChange: + m_PersistentCalls: + m_Calls: [] + minThreshold: 1 + squezeDamageScalor: 1 --- !u!1 &437176298 GameObject: m_ObjectHideFlags: 0 @@ -431,6 +499,7 @@ GameObject: - component: {fileID: 437176300} - component: {fileID: 437176299} - component: {fileID: 437176302} + - component: {fileID: 437176303} m_Layer: 0 m_Name: EnemyTest (2) m_TagString: Untagged @@ -567,6 +636,39 @@ Rigidbody2D: m_SleepingMode: 1 m_CollisionDetection: 1 m_Constraints: 0 +--- !u!114 &437176303 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 437176298} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1fdfc885f1a69704b893825cf9e616ba, type: 3} + m_Name: + m_EditorClassIdentifier: + maxHealth: 100 + OnHealthZero: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 437176303} + m_TargetAssemblyTypeName: HealthComponent, Assembly-CSharp + m_MethodName: SimpleKill + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + OnHealthChange: + m_PersistentCalls: + m_Calls: [] + minThreshold: 1 + squezeDamageScalor: 1 --- !u!1 &442848047 GameObject: m_ObjectHideFlags: 0 @@ -578,6 +680,7 @@ GameObject: - component: {fileID: 442848048} - component: {fileID: 442848050} - component: {fileID: 442848049} + - component: {fileID: 442848051} m_Layer: 5 m_Name: Health m_TagString: Untagged @@ -701,6 +804,21 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 442848047} m_CullTransparentMesh: 1 +--- !u!114 &442848051 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 442848047} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6ea817cc94396c24199c7d5b0f34e889, type: 3} + m_Name: + m_EditorClassIdentifier: + padding: 'Health: ' + healthText: {fileID: 442848049} + healthComponent: {fileID: 1451580751} --- !u!1 &484915623 GameObject: m_ObjectHideFlags: 0 @@ -919,8 +1037,26 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: maxHealth: 100 - currentHealth: 0 - healthText: {fileID: 442848049} + OnHealthZero: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1451580751} + m_TargetAssemblyTypeName: HealthComponent, Assembly-CSharp + m_MethodName: SimpleKill + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + OnHealthChange: + m_PersistentCalls: + m_Calls: [] + minThreshold: 1 + squezeDamageScalor: 0 --- !u!114 &1451580752 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Player/HealthComponent.cs b/Assets/Scripts/Player/HealthComponent.cs new file mode 100644 index 0000000..d02a05f --- /dev/null +++ b/Assets/Scripts/Player/HealthComponent.cs @@ -0,0 +1,46 @@ +using UnityEngine; +using UnityEngine.Events; +using TMPro; + +public class HealthComponent : MonoBehaviour, ISquezeDamageReceiver +{ + [SerializeField] int maxHealth = 100; + public int currentHealth { get; private set; } + + public UnityEvent OnHealthZero; + public UnityEvent OnHealthChange; + + [Header("Squeze Damage")] + [SerializeField] + float minThreshold = 1f; + + [SerializeField] + float squezeDamageScalor = 1f; + + void Awake() + { + currentHealth = maxHealth; + } + + public void TakeDamage(int damage) + { + currentHealth -= damage; + OnHealthChange?.Invoke(currentHealth + damage, currentHealth); + + if (currentHealth <= 0) + OnHealthZero?.Invoke(); + } + + public void TakeSquezeDamage(float squezeDamage) + { + Debug.Log($"Taking {squezeDamage}"); + if (squezeDamage < minThreshold) return; + + TakeDamage((int) Mathf.Round(squezeDamage * squezeDamageScalor)); + } + + public void SimpleKill() + { + Destroy(gameObject); + } +} diff --git a/Assets/Scripts/Player/PlayerHP.cs.meta b/Assets/Scripts/Player/HealthComponent.cs.meta similarity index 100% rename from Assets/Scripts/Player/PlayerHP.cs.meta rename to Assets/Scripts/Player/HealthComponent.cs.meta diff --git a/Assets/Scripts/Player/PlayerHP.cs b/Assets/Scripts/Player/PlayerHP.cs deleted file mode 100644 index 9c70ec6..0000000 --- a/Assets/Scripts/Player/PlayerHP.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using TMPro; - -public class PlayerHP : MonoBehaviour -{ - public int maxHealth = 100; - public int currentHealth; - public TextMeshProUGUI healthText; - void Start() - { - currentHealth = maxHealth; - } - - public void Update() - { - if (currentHealth <= 0) - { - // TODO: Game Over - } - if (healthText != null && currentHealth > 0) - { - healthText.text = "Health: " + currentHealth; - } - else if (healthText != null && currentHealth <= 0) - healthText.text = "Health: 0"; - - if (Input.GetKeyDown(KeyCode.Space)) - TakeDamage(5); - } - - public void TakeDamage(float damage) - { - currentHealth -= (int)damage; - } -} diff --git a/Assets/Scripts/Rope/ISquezeDamageReceiver.cs b/Assets/Scripts/Rope/ISquezeDamageReceiver.cs new file mode 100644 index 0000000..8b83043 --- /dev/null +++ b/Assets/Scripts/Rope/ISquezeDamageReceiver.cs @@ -0,0 +1,4 @@ +public interface ISquezeDamageReceiver +{ + public void TakeSquezeDamage(float squezeDamage); +} \ No newline at end of file diff --git a/Assets/Scripts/Rope/ISquezeDamageReceiver.cs.meta b/Assets/Scripts/Rope/ISquezeDamageReceiver.cs.meta new file mode 100644 index 0000000..50d1188 --- /dev/null +++ b/Assets/Scripts/Rope/ISquezeDamageReceiver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d31d8fbcb6322ba4ba6891dba7d49bd0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Rope/RopeSimulator.cs b/Assets/Scripts/Rope/RopeSimulator.cs index b418554..729df7a 100644 --- a/Assets/Scripts/Rope/RopeSimulator.cs +++ b/Assets/Scripts/Rope/RopeSimulator.cs @@ -51,10 +51,10 @@ public class RopeSimulator : MonoBehaviour public Vector2 testPos; - Vector2 prevStartPos; - Rope rope; + Dictionary colliderToSquezeForce = new(); + private void Start() { //rope = new RopeBuilder() @@ -100,6 +100,8 @@ public class RopeSimulator : MonoBehaviour private void Update() { + colliderToSquezeForce.Clear(); + rope.points.First().position = start.position; rope.points.Last().position = end.position; @@ -128,7 +130,14 @@ public class RopeSimulator : MonoBehaviour start.gameObject.GetComponent().AddForce(pullDirection * overshoot * pullForce); } - prevStartPos = start.position; + // Handle squeze kills + foreach (var collider in colliderToSquezeForce) + { + ISquezeDamageReceiver squezeDamageReceiver = collider.Key.GetComponent(); + if (squezeDamageReceiver == null) continue; + + squezeDamageReceiver.TakeSquezeDamage(collider.Value); + } } private void OnDrawGizmos() @@ -216,10 +225,17 @@ public class RopeSimulator : MonoBehaviour Collider2D hitCollider = Physics2D.OverlapCircle(p.position, ropeRadius, staticColliderMask); if (hitCollider == null) return; + // Register the squeze force this rope particle is squezing the collider Vector2 resolvedPos = hitCollider.ClosestPoint(p.position); - Vector2 penetrationDir = (resolvedPos - p.position).normalized; - Vector2 finalPos = resolvedPos - penetrationDir * ropeRadius; - + Vector2 penetration = resolvedPos - p.position; + Vector2 finalPos = resolvedPos - penetration.normalized * ropeRadius; + + float squezeForce; + if (!colliderToSquezeForce.TryGetValue(hitCollider, out squezeForce)) + colliderToSquezeForce.Add(hitCollider, squezeForce + penetration.magnitude); + else + colliderToSquezeForce[hitCollider] = squezeForce + penetration.magnitude; + p.position = finalPos; } diff --git a/Assets/Scripts/UI.meta b/Assets/Scripts/UI.meta new file mode 100644 index 0000000..5af4230 --- /dev/null +++ b/Assets/Scripts/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8b645cb8aa203484aaefb2b6f86e696c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UI/HealthDisplay.cs b/Assets/Scripts/UI/HealthDisplay.cs new file mode 100644 index 0000000..ae7af02 --- /dev/null +++ b/Assets/Scripts/UI/HealthDisplay.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using TMPro; + +public class HealthDisplay : MonoBehaviour +{ + [SerializeField] string padding = "Health: "; + [SerializeField] TextMeshProUGUI healthText; + [SerializeField] HealthComponent healthComponent; + + private void Start() + { + healthText.text = padding + healthComponent.currentHealth; + } + + private void OnEnable() + { + healthComponent.OnHealthChange.AddListener(UpdateHealth); + } + + private void OnDisable() + { + healthComponent.OnHealthChange.RemoveListener(UpdateHealth); + } + + public void UpdateHealth(int prevHealth, int newHealth) + { + healthText.text = padding + healthComponent.currentHealth; + } +} diff --git a/Assets/Scripts/UI/HealthDisplay.cs.meta b/Assets/Scripts/UI/HealthDisplay.cs.meta new file mode 100644 index 0000000..36b9a51 --- /dev/null +++ b/Assets/Scripts/UI/HealthDisplay.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ea817cc94396c24199c7d5b0f34e889 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: