From 03ca23d48473a99e3b9c5685dbbb8d050825f696 Mon Sep 17 00:00:00 2001 From: henriquenakashima Date: Sun, 20 Sep 2020 22:45:42 -0400 Subject: [PATCH] Create StatusUI --- Assets/Battle/BattleParticipant.cs | 45 ++- .../Battle/CardsMonsters/GolemChargeMCard.cs | 2 + .../CardsMonsters/GraniteDefenseMCard.cs | 4 +- ...roUI.prefab => BattleParticipantUI.prefab} | 296 +++++++++++++++++- ...b.meta => BattleParticipantUI.prefab.meta} | 0 Assets/Battle/UI/HeroInfoUI.cs | 3 + Assets/Battle/UI/StatusUI.cs | 47 +++ Assets/Battle/UI/StatusUI.cs.meta | 11 + Assets/Battle/UI/stun_icon.png | Bin 0 -> 8227 bytes Assets/Battle/UI/stun_icon.png.meta | 92 ++++++ TODO.txt | 1 - 11 files changed, 484 insertions(+), 17 deletions(-) rename Assets/Battle/UI/{HeroUI.prefab => BattleParticipantUI.prefab} (66%) rename Assets/Battle/UI/{HeroUI.prefab.meta => BattleParticipantUI.prefab.meta} (100%) create mode 100644 Assets/Battle/UI/StatusUI.cs create mode 100644 Assets/Battle/UI/StatusUI.cs.meta create mode 100644 Assets/Battle/UI/stun_icon.png create mode 100644 Assets/Battle/UI/stun_icon.png.meta diff --git a/Assets/Battle/BattleParticipant.cs b/Assets/Battle/BattleParticipant.cs index 37dd67f..e917bda 100644 --- a/Assets/Battle/BattleParticipant.cs +++ b/Assets/Battle/BattleParticipant.cs @@ -5,8 +5,9 @@ using UnityEngine; public class BattleParticipant { - public delegate void DeathAction(BattleParticipant participant); - public event DeathAction OnDeath; + public delegate void BattleParticipantUpdateAction(BattleParticipant participant); + public event BattleParticipantUpdateAction OnDeath; + public event BattleParticipantUpdateAction OnStatusChanged; protected bool isHero; protected string displayName; @@ -55,6 +56,7 @@ public class BattleParticipant public void CheckState() { if (this.hp <= 0) { this.dead = true; + WipeStatus(); TriggerOnDeath(); } } @@ -99,20 +101,35 @@ public class BattleParticipant } public int AddStatus(BattleStatus status, int amount) { + if (amount <= 0) { + return 0; + } + int currentAmount; this.statuses.TryGetValue(status, out currentAmount); this.statuses[status] = currentAmount + amount; + TriggerOnStatusChanged(); return amount; } public void TickStatuses() { - Dictionary newStatuses = new Dictionary(); - foreach (KeyValuePair pair in this.statuses) { - if (pair.Value >= 1) { - newStatuses[pair.Key] = pair.Value - 1; + if (this.statuses.Count > 0) { + Dictionary newStatuses = new Dictionary(); + foreach (KeyValuePair pair in this.statuses) { + if (pair.Value > 1) { + newStatuses[pair.Key] = pair.Value - 1; + } } + this.statuses = newStatuses; + TriggerOnStatusChanged(); + } + } + + public void WipeStatus() { + if (this.statuses.Count > 0) { + this.statuses = new Dictionary(); + TriggerOnStatusChanged(); } - this.statuses = newStatuses; } public bool CanUseCard(BaseCard card) { @@ -122,4 +139,18 @@ public class BattleParticipant public bool HasStatus(BattleStatus status) { return this.statuses.ContainsKey(status); } + + public int GetStatusAmount(BattleStatus status) { + if (!this.statuses.ContainsKey(status)) { + return 0; + } else { + return this.statuses[status]; + } + } + + private void TriggerOnStatusChanged() { + if (this.OnStatusChanged != null) { + this.OnStatusChanged(this); + } + } } diff --git a/Assets/Battle/CardsMonsters/GolemChargeMCard.cs b/Assets/Battle/CardsMonsters/GolemChargeMCard.cs index 74ce15c..cfe058f 100644 --- a/Assets/Battle/CardsMonsters/GolemChargeMCard.cs +++ b/Assets/Battle/CardsMonsters/GolemChargeMCard.cs @@ -11,6 +11,8 @@ public class GolemChargeMCard : MonsterCard } public override IEnumerator Use(IBattleEffectApplier effectApplier, MonsterViewpoint monsterViewpoint) { + yield return new WaitForSeconds(0.5f); + BattleParticipant target = AIUtils.GetFarthestHero(monsterViewpoint, this.owner); DealDamageEffect damageEffect = new DealDamageEffect(target, 4); effectApplier.Apply(damageEffect); diff --git a/Assets/Battle/CardsMonsters/GraniteDefenseMCard.cs b/Assets/Battle/CardsMonsters/GraniteDefenseMCard.cs index 6e867e1..ab7789a 100644 --- a/Assets/Battle/CardsMonsters/GraniteDefenseMCard.cs +++ b/Assets/Battle/CardsMonsters/GraniteDefenseMCard.cs @@ -10,11 +10,11 @@ public class GraniteDefenseMCard : MonsterCard } public override IEnumerator Use(IBattleEffectApplier effectApplier, MonsterViewpoint monsterViewpoint) { - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(0.6f); foreach (BattleMonster monster in monsterViewpoint.Monsters) { if (monster != this.owner) { effectApplier.Apply(new BlockEffect(monster, 5)); - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(0.3f); } } } diff --git a/Assets/Battle/UI/HeroUI.prefab b/Assets/Battle/UI/BattleParticipantUI.prefab similarity index 66% rename from Assets/Battle/UI/HeroUI.prefab rename to Assets/Battle/UI/BattleParticipantUI.prefab index 25afd88..73f0f34 100644 --- a/Assets/Battle/UI/HeroUI.prefab +++ b/Assets/Battle/UI/BattleParticipantUI.prefab @@ -34,8 +34,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -36, y: 0} - m_SizeDelta: {x: 17, y: 14.8} + m_AnchoredPosition: {x: -36, y: 0.40002} + m_SizeDelta: {x: 17, y: 16.915695} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &7203125139980703040 CanvasRenderer: @@ -66,8 +66,8 @@ MonoBehaviour: m_Calls: [] m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 12 - m_FontStyle: 0 + m_FontSize: 14 + m_FontStyle: 1 m_BestFit: 0 m_MinSize: 1 m_MaxSize: 40 @@ -78,6 +78,154 @@ MonoBehaviour: m_VerticalOverflow: 0 m_LineSpacing: 1 m_Text: 56 +--- !u!1 &3426763279947371280 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2365314723301749520} + - component: {fileID: 2687845506595039125} + - component: {fileID: 7861691439794345590} + m_Layer: 5 + m_Name: BG + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2365314723301749520 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3426763279947371280} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5364248411365301727} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -53.76, y: 60.32} + m_SizeDelta: {x: 16.523172, y: 17.074677} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2687845506595039125 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3426763279947371280} + m_CullTransparentMesh: 0 +--- !u!114 &7861691439794345590 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3426763279947371280} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 0.30588236} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: ff1a435c8e6ef4a46aeb34ba613ce13d, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 0 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &3730468488252910637 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7872829101071880504} + - component: {fileID: 7145260895785022369} + - component: {fileID: 1306121800800203574} + m_Layer: 5 + m_Name: StunIcon + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7872829101071880504 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3730468488252910637} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5364248411365301727} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -53.76, y: 60.32} + m_SizeDelta: {x: 16.522865, y: 17.07425} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7145260895785022369 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3730468488252910637} + m_CullTransparentMesh: 0 +--- !u!114 &1306121800800203574 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3730468488252910637} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0.9715784, b: 0.3160377, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: dc422435e5172774ca9ddc33364d1a6f, type: 3} + m_Type: 0 + m_PreserveAspect: 1 + m_FillCenter: 1 + m_FillMethod: 0 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 --- !u!1 &5172729878808660606 GameObject: m_ObjectHideFlags: 0 @@ -193,6 +341,60 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 60} m_SizeDelta: {x: 100, y: 100} m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &5356782115194992290 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5364248411365301727} + - component: {fileID: 2488458570692802998} + m_Layer: 5 + m_Name: StatusMarkers + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5364248411365301727 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5356782115194992290} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2365314723301749520} + - {fileID: 7872829101071880504} + - {fileID: 501555061161187130} + m_Father: {fileID: 6071241564507600362} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2488458570692802998 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5356782115194992290} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d86314823afd5c34396777dcb49e6093, type: 3} + m_Name: + m_EditorClassIdentifier: + backgroundImage: {fileID: 7861691439794345590} + stunImage: {fileID: 1306121800800203574} + turnsText: {fileID: 2986296803404415245} --- !u!1 &5574000899179897583 GameObject: m_ObjectHideFlags: 0 @@ -227,8 +429,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -36, y: 0} - m_SizeDelta: {x: 17, y: 12} + m_AnchoredPosition: {x: -36, y: 0.4} + m_SizeDelta: {x: 17, y: 16.91568} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &8600655002061634105 CanvasRenderer: @@ -542,7 +744,7 @@ GameObject: - component: {fileID: 6071241564507600362} - component: {fileID: 6641511084601005557} m_Layer: 5 - m_Name: HeroUI + m_Name: BattleParticipantUI m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -562,6 +764,7 @@ RectTransform: - {fileID: 6071241564363553667} - {fileID: 6071241564411437881} - {fileID: 1054158240845704231} + - {fileID: 5364248411365301727} m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -588,3 +791,82 @@ MonoBehaviour: hpText: {fileID: 2548384344736816241} blockGroup: {fileID: 5194869534592792291} blockText: {fileID: 1400733402613879005} + statusUI: {fileID: 2488458570692802998} +--- !u!1 &7709810175605034872 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 501555061161187130} + - component: {fileID: 2941542102252663832} + - component: {fileID: 2986296803404415245} + m_Layer: 5 + m_Name: TurnsText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &501555061161187130 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7709810175605034872} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5364248411365301727} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -61.9, y: 69.1} + m_SizeDelta: {x: 13, y: 13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2941542102252663832 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7709810175605034872} + m_CullTransparentMesh: 0 +--- !u!114 &2986296803404415245 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7709810175605034872} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.8490566, g: 0.8490566, b: 0.8490566, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 10 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 1 diff --git a/Assets/Battle/UI/HeroUI.prefab.meta b/Assets/Battle/UI/BattleParticipantUI.prefab.meta similarity index 100% rename from Assets/Battle/UI/HeroUI.prefab.meta rename to Assets/Battle/UI/BattleParticipantUI.prefab.meta diff --git a/Assets/Battle/UI/HeroInfoUI.cs b/Assets/Battle/UI/HeroInfoUI.cs index ec7cd14..1ad03c3 100644 --- a/Assets/Battle/UI/HeroInfoUI.cs +++ b/Assets/Battle/UI/HeroInfoUI.cs @@ -13,6 +13,7 @@ public class HeroInfoUI : MonoBehaviour public Text hpText; public GameObject blockGroup; public Text blockText; + public StatusUI statusUI; private int renderedHP = -1; private int renderedMaxHP = -1; @@ -26,6 +27,8 @@ public class HeroInfoUI : MonoBehaviour public void Init(GameObject sprite, BattleParticipant battleParticipant) { this.target = sprite; this.battleParticipant = battleParticipant; + + this.statusUI.Init(battleParticipant); } // Start is called before the first frame update diff --git a/Assets/Battle/UI/StatusUI.cs b/Assets/Battle/UI/StatusUI.cs new file mode 100644 index 0000000..697b1fb --- /dev/null +++ b/Assets/Battle/UI/StatusUI.cs @@ -0,0 +1,47 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class StatusUI : MonoBehaviour +{ + public Image backgroundImage; + public Image stunImage; + public Text turnsText; + + private BattleParticipant battleParticipant; + + public void Init(BattleParticipant battleParticipant) { + this.battleParticipant = battleParticipant; + + this.battleParticipant.OnStatusChanged += this.NotifyBattleStatusChanged; + } + + // Start is called before the first frame update + void Start() + { + UpdateAppearance(); + } + + public void NotifyBattleStatusChanged(BattleParticipant updatedParticipant) { + if (updatedParticipant != this.battleParticipant) { + throw new System.InvalidOperationException( + "NotifyBattleStatusChanged was notified about a different participant."); + } + UpdateAppearance(); + } + + private void UpdateAppearance() { + int statusCount = 0; + if (battleParticipant.HasStatus(BattleStatus.Stun)) { + statusCount++; + this.stunImage.enabled = true; + this.turnsText.enabled = true; + this.turnsText.text = "" + battleParticipant.GetStatusAmount(BattleStatus.Stun); + } else { + this.stunImage.enabled = false; + this.turnsText.enabled = false; + } + this.backgroundImage.enabled = (statusCount > 0); + } +} diff --git a/Assets/Battle/UI/StatusUI.cs.meta b/Assets/Battle/UI/StatusUI.cs.meta new file mode 100644 index 0000000..c7891c7 --- /dev/null +++ b/Assets/Battle/UI/StatusUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d86314823afd5c34396777dcb49e6093 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Battle/UI/stun_icon.png b/Assets/Battle/UI/stun_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b8c33c08227b4e8ce1e9643c64b2869b09920c2f GIT binary patch literal 8227 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