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;
}
}