using System; using Microsoft.Xna.Framework.Graphics; namespace FreedomFighter; /// /// Port of TOmegaBitmapFont: a fixed-cell bitmap font backed by an image list item, /// with mutable color/alpha state (the credits animate Alpha on the shared font). /// public class BitmapFont { public string Characters = ""; public OmegaImage Image = null!; public int Red = 255, Green = 255, Blue = 255; public int Alpha = 255; public int CharWidth => Image.TileWidth; public int CharHeight => Image.TileHeight; public BitmapFont(OmegaImage image, string characters) { Image = image; Characters = characters; } public void PrintFast(SpriteBatch sb, float x, float y, char c) { int idx = Characters.IndexOf(c); if (idx < 0) return; Image.Draw(sb, x, y, 0, 0, 0, 1, 1, Red, Green, Blue, Math.Clamp(Alpha, 0, 255), idx); } public void Print(SpriteBatch sb, float x, float y, string text) { for (int i = 0; i < text.Length; i++) PrintFast(sb, x + i * CharWidth, y, text[i]); } } /// /// Port of the TGameText helper (GameText.pas): typewriter printing and /// fade in/out of text through a bitmap font's shared Alpha. /// public class GameText { string _text; int _length; int _curChar; int _maxLength; int _timer; int _speed = 10; bool _done; readonly BitmapFont _font; public GameText(string msg, int rowLength, BitmapFont font) { _text = msg; _length = msg.Length; _maxLength = rowLength; _font = font; } public void SetText(string msg) { _text = msg; _length = msg.Length; _curChar = 0; _timer = 0; } public void SetSpeed(int speed) => _speed = speed; public bool IsDone => _done; public string GetText() => _text; public int GetLength() => _length * _font.CharWidth; // The Pascal original indexed the 1-based string with i = 0..CurChar; index 0 was a no-op. void PrintChars(SpriteBatch sb, float x, float y, int upTo) { for (int i = 1; i <= upTo && i <= _length; i++) { char c = _text[i - 1]; if (i <= _maxLength) _font.PrintFast(sb, x + i * _font.CharWidth, y, c); else { int tempChar = i; while (tempChar > _maxLength) tempChar -= _maxLength; _font.PrintFast(sb, x + tempChar * 12, y + (int)Math.Ceiling(i / (double)_maxLength) * 24 - 24, c); } } } public void TypePrint(SpriteBatch sb, float x, float y) { _done = false; PrintChars(sb, x, y, _curChar); if (_curChar < _length) { _timer++; if (_timer > _speed) { _curChar++; if (_curChar <= _length && _curChar >= 1 && _text[_curChar - 1] == ' ') _curChar++; _timer = 0; } } else _done = true; } public void FadeIn(SpriteBatch sb, float x, float y, int speed) { _done = false; PrintChars(sb, x, y, _length); _timer++; if (_timer > speed && _font.Alpha < 255) _font.Alpha++; else _done = true; // original quirk: also "done" while the timer is still counting } public void FadeOut(SpriteBatch sb, float x, float y, int speed) { _done = false; PrintChars(sb, x, y, _length); _timer++; if (_timer > speed && _font.Alpha > 0) _font.Alpha--; else _done = true; } public void Reset() { _curChar = 0; _timer = 0; _speed = 10; _done = false; } }