diff --git a/EndlessClient/Rendering/Character/CharacterRenderer.cs b/EndlessClient/Rendering/Character/CharacterRenderer.cs index c604677ab..d4d4c07f5 100644 --- a/EndlessClient/Rendering/Character/CharacterRenderer.cs +++ b/EndlessClient/Rendering/Character/CharacterRenderer.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using EndlessClient.Audio; -using EndlessClient.GameExecution; using EndlessClient.Input; using EndlessClient.Rendering.CharacterProperties; using EndlessClient.Rendering.Chat; @@ -15,7 +14,6 @@ using EOLib.Domain.Extensions; using EOLib.Domain.Map; using EOLib.Domain.Spells; -using EOLib.Graphics; using EOLib.IO.Map; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -26,7 +24,7 @@ namespace EndlessClient.Rendering.Character { public class CharacterRenderer : DrawableGameComponent, ICharacterRenderer { - private readonly object _rt_locker_ = new object(); + private readonly object _rt_locker_ = new(); private readonly IRenderTargetFactory _renderTargetFactory; private readonly IHealthBarRendererFactory _healthBarRendererFactory; @@ -157,6 +155,7 @@ public override void Initialize() _nameLabel.DrawPosition = GetNameLabelPosition(); _healthBarRenderer = _healthBarRendererFactory.CreateHealthBarRenderer(this); + Game.Components.Add(_healthBarRenderer); } base.Initialize(); @@ -195,9 +194,6 @@ public override void Update(GameTime gameTime) if (!_isUiControl) { UpdateNameLabel(); - - _healthBarRenderer?.Update(gameTime); - CheckForDead(); } @@ -260,9 +256,6 @@ public void DrawToSpriteBatch(SpriteBatch spriteBatch) } _effectRenderer.DrawInFrontOfTarget(spriteBatch); - - if (!_isUiControl) - _healthBarRenderer?.DrawToSpriteBatch(spriteBatch); } public void ShowName() => _showName = true; @@ -534,9 +527,20 @@ protected override void Dispose(bool disposing) { _outline?.Dispose(); - if (Game != null && Game.Components != null && Game.Components.Contains(_nameLabel)) - Game.Components.Remove(_nameLabel); + if (Game != null && Game.Components != null) + { + if (Game.Components.Contains(_nameLabel)) + { + Game.Components.Remove(_nameLabel); + } + + if (Game.Components.Contains(_healthBarRenderer)) + { + Game.Components.Remove(_healthBarRenderer); + } + } _nameLabel?.Dispose(); + _healthBarRenderer?.Dispose(); if (_chatBubble.IsValueCreated) _chatBubble.Value?.Dispose(); diff --git a/EndlessClient/Rendering/Factories/HealthBarRendererFactory.cs b/EndlessClient/Rendering/Factories/HealthBarRendererFactory.cs index 662c60bf8..89187df97 100644 --- a/EndlessClient/Rendering/Factories/HealthBarRendererFactory.cs +++ b/EndlessClient/Rendering/Factories/HealthBarRendererFactory.cs @@ -1,4 +1,5 @@ using AutomaticTypeMapper; +using EndlessClient.GameExecution; using EOLib.Graphics; namespace EndlessClient.Rendering.Factories @@ -6,16 +7,19 @@ namespace EndlessClient.Rendering.Factories [AutoMappedType] public class HealthBarRendererFactory : IHealthBarRendererFactory { + private readonly IEndlessGameProvider _endlessGameProvider; private readonly INativeGraphicsManager _nativeGraphicsManager; - public HealthBarRendererFactory(INativeGraphicsManager nativeGraphicsManager) + public HealthBarRendererFactory(IEndlessGameProvider endlessGameProvider, + INativeGraphicsManager nativeGraphicsManager) { + _endlessGameProvider = endlessGameProvider; _nativeGraphicsManager = nativeGraphicsManager; } public IHealthBarRenderer CreateHealthBarRenderer(IMapActor parentReference) { - return new HealthBarRenderer(_nativeGraphicsManager, parentReference); + return new HealthBarRenderer(_endlessGameProvider, _nativeGraphicsManager, parentReference); } } diff --git a/EndlessClient/Rendering/HealthBarRenderer.cs b/EndlessClient/Rendering/HealthBarRenderer.cs index 838b03b42..c44e6cfb6 100644 --- a/EndlessClient/Rendering/HealthBarRenderer.cs +++ b/EndlessClient/Rendering/HealthBarRenderer.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using EndlessClient.GameExecution; using EOLib.Graphics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -8,13 +9,15 @@ namespace EndlessClient.Rendering { - public class HealthBarRenderer : IHealthBarRenderer + public class HealthBarRenderer : DrawableGameComponent, IHealthBarRenderer { private const int DigitWidth = 9; private readonly IMapActor _parentReference; + private readonly SpriteBatch _spriteBatch; private readonly Texture2D _sourceTexture; + private static readonly Point _numberSpritesOffset, _healthBarSpritesOffset; private static readonly Rectangle _healthBarBackgroundSource; @@ -26,8 +29,6 @@ public class HealthBarRenderer : IHealthBarRenderer private float _frameOffset; private Vector2 _damageCounterPosition, _healthBarPosition; - public bool Visible { get; private set; } - static HealthBarRenderer() { _numberSpritesOffset = new Point(40, 28); @@ -35,17 +36,29 @@ static HealthBarRenderer() _healthBarBackgroundSource = new Rectangle(0, 28, 40, 7); } - public HealthBarRenderer(INativeGraphicsManager nativeGraphicsManager, + public HealthBarRenderer(IEndlessGameProvider endlessGameProvider, + INativeGraphicsManager nativeGraphicsManager, IMapActor parentReference) + : base((Game)endlessGameProvider.Game) { _parentReference = parentReference; + + _spriteBatch = new SpriteBatch(Game.GraphicsDevice); _sourceTexture = nativeGraphicsManager.TextureFromResource(GFXTypes.PostLoginUI, 58, true); - _numberSourceRectangles = new List(); + + _numberSourceRectangles = []; + UpdateOrder = DrawOrder = 99; + Enabled = Visible = false; + } + + public override void Initialize() + { + base.Initialize(); } public void SetDamage(Option value, int percentHealth, Action doneCallback = null) { - Visible = true; + Enabled = Visible = true; _isMiss = !value.HasValue; _doneCallback = doneCallback; _frameOffset = 0; @@ -64,7 +77,7 @@ public void SetDamage(Option value, int percentHealth, Action doneCallback public void SetHealth(int value, int percentHealth, Action doneCallback = null) { - Visible = true; + Enabled = Visible = true; _isMiss = false; _doneCallback = doneCallback; _frameOffset = 0; @@ -78,14 +91,12 @@ public void SetHealth(int value, int percentHealth, Action doneCallback = null) _healthBarSourceRectangle = new Rectangle(_healthBarSpritesOffset + _healthBarSourceRectangle.Location, _healthBarSourceRectangle.Size); } - public void Update(GameTime gameTime) + public override void Update(GameTime gameTime) { - if (!Visible) return; - _frameOffset += .1f; if (_frameOffset > 4) { - Visible = false; + Enabled = Visible = false; _doneCallback?.Invoke(); } @@ -108,19 +119,31 @@ public void Update(GameTime gameTime) } } - public void DrawToSpriteBatch(SpriteBatch spriteBatch) + public override void Draw(GameTime gameTime) { - if (!Visible) return; + _spriteBatch.Begin(); var numberNdx = 0; foreach (var numberSource in _numberSourceRectangles) { - spriteBatch.Draw(_sourceTexture, _damageCounterPosition + new Vector2(numberNdx * DigitWidth, 0), numberSource, Color.White); + _spriteBatch.Draw(_sourceTexture, _damageCounterPosition + new Vector2(numberNdx * DigitWidth, 0), numberSource, Color.White); numberNdx++; } - spriteBatch.Draw(_sourceTexture, _healthBarPosition, _healthBarBackgroundSource, Color.White); - spriteBatch.Draw(_sourceTexture, _healthBarPosition, _healthBarSourceRectangle, Color.White); + _spriteBatch.Draw(_sourceTexture, _healthBarPosition, _healthBarBackgroundSource, Color.White); + _spriteBatch.Draw(_sourceTexture, _healthBarPosition, _healthBarSourceRectangle, Color.White); + + _spriteBatch.End(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _spriteBatch.Dispose(); + } + + base.Dispose(disposing); } private static IEnumerable GetNumberSourceRectangles(int value, bool isHeal) @@ -150,16 +173,10 @@ private static Rectangle GetHealthBarSourceRectangle(int percentHealth) } } - public interface IHealthBarRenderer + public interface IHealthBarRenderer : IDrawable, IGameComponent, IDisposable { - bool Visible { get; } - void SetDamage(Option value, int percentHealth, Action doneCallback = null); void SetHealth(int value, int percentHealth, Action doneCallback = null); - - void Update(GameTime gameTime); - - void DrawToSpriteBatch(SpriteBatch spriteBatch); } } diff --git a/EndlessClient/Rendering/NPC/NPCRenderer.cs b/EndlessClient/Rendering/NPC/NPCRenderer.cs index fc8d4fd4d..a104739bb 100644 --- a/EndlessClient/Rendering/NPC/NPCRenderer.cs +++ b/EndlessClient/Rendering/NPC/NPCRenderer.cs @@ -129,6 +129,8 @@ public override void Initialize() _npcSpriteDataCache.Populate(graphic); _isBlankSprite = _npcSpriteDataCache.IsBlankSprite(graphic); + Game.Components.Add(_healthBarRenderer); + base.Initialize(); } @@ -155,7 +157,6 @@ public override void Update(GameTime gameTime) } _effectRenderer.Update(); - _healthBarRenderer.Update(gameTime); base.Update(gameTime); } @@ -183,8 +184,6 @@ public void DrawToSpriteBatch(SpriteBatch spriteBatch) if (_npcRenderTarget != null) spriteBatch.Draw(_npcRenderTarget, Vector2.Zero, Color.White); _effectRenderer.DrawInFrontOfTarget(spriteBatch); - - _healthBarRenderer.DrawToSpriteBatch(spriteBatch); } public void StartDying() @@ -330,6 +329,9 @@ protected override void Dispose(bool disposing) { if (disposing) { + Game.Components.Remove(_healthBarRenderer); + _healthBarRenderer.Dispose(); + _nameLabel.Dispose(); _chatBubble?.Dispose(); _spriteBatch?.Dispose();