0
\$\begingroup\$

I am making an xna game which contains turn-based RPG battle elements. Any good game that features turn-based battle has to have a good feedback to the user.

For example, When my guy attacks, there should be a text popup that says something like "HERO DOES 15 DMG!". And this text should disappear several seconds after.

I am currently able to put text on the screen via standard spritefont drawing. However, in order to make it disappear I am currently using bools and a timer. I have been doing research on timing related stuff but I seem to be very bad at it.

Using some of the suggestions I have received, I have made a messagesystem class. But I am still confused about the implementation. Here is the new code:

public class MessageSystem
    {

        public static readonly MessageSystem Instance = new MessageSystem();
        public float timenow;

        struct Message
        {
            public SpriteFont Font;
            public string Data;
            public Vector2 Position;
            public float Duration;
            public bool isActive { get; set; }

        }

        List<Message> Messages = new List<Message>();

        public MessageSystem()
        {

        }

        public void Show(string data, Vector2 pos, SpriteFont font, float duration)
        {
            Messages.Add(new Message() { Data = data, Font = font, Position = pos, Duration = duration });
        }
        public void Update(GameTime gameTime)
        {
            timenow += (float)gameTime.ElapsedGameTime.TotalSeconds;

            for (int i = 0; i < Messages.Count; )
            {
                if (Messages[i].Duration < timenow)
                {
                    Messages.RemoveAt(i);
                    continue;
                }
                i++;
            }
        }


        public void Draw(SpriteBatch batch)
        {

            foreach (Message msg in Messages)
            {
                batch.DrawString(msg.Font, msg.Data, msg.Position, Color.Lime);
            }

        }

    }

Here is the implementation part:

if (p1atktimer >= 10)
            {
                AttackMsg.Show(playerBattler.Name + " attacks furiously!", battlemsgs, battlefont, 2.0f);
                DealDmgFromLeft(gameTime);
                p1atktimer = 0;
                timenow = 0;
            }

In my update method I just have:

Attackmsg.Update(gameTime);

And similarly, in my Draw method I have:

Attackmsg.Draw(spriteBatch);

So, it goes away when it is supposed to, but it does not appear again when the p1atktimer condition becomes true again. I guess i have to surround the attackmsg.Draw(spriteBatch) command with conditionals instead of the show? But this brings me back to my previous question: Do I have to make bools for everytime I want to show this kind of text.

Let's continue with this example, I am going to make a bool atkmsgshowing = false. And make it true when someone's attackguage reaches 10. Because, if I do not do this, the msg works only once. So then, the attacker attacks, and I will make the bool true. When the attack ends, atkmsgshowing will go back to false. Doesn't this defeat the purpose of making a MessageSystem class?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$
public class Message 
{
  public string Text {get;set;}
  public TimeSpan Appeared {get;set;}
  public Vector2 Position {get;set;}
}

static readonly Vector2 BattleTextDisplacement = new Vector2(80, -100);
List<Message> messages;

Then to add a message

messages.Add(new Message() {Text = "Player attacks", 
   Appeared = gameTime.TotalGameTime,
   Position = playerBattler.Position + BattleTextDisplacement});

And then to display them:

foreach (var message in messages)
  spriteBatch.DrawString(battlefont, message.Text, message.Position, Color.Lime)

To remove old messages:

while (messages.Count > 0 && 
       messages[0].Appeared + MaxAgeMessage > gameTime.TotalGameTime)
  message.RemoveAt(0);

And of course, making the text float up on the screen is easy now, simply change its position (or use the age of the message to figure out where the position should be).

A lot of the code can be put into methods in the Message class itself, so instead of drawing the text you can have a Message.DrawMessage(battlefont, spriteBatch), this way you can make a subclass that draws the text differently (such as having a graphic behind it, or display an animation instead of text).

\$\endgroup\$
2
  • \$\begingroup\$ lol, at the same time ;) \$\endgroup\$
    – Blau
    Commented May 3, 2012 at 22:51
  • \$\begingroup\$ Hi guys, thanks for the tips. I have tried both of your suggestions and ended up implementing Blau's. But I still have some problems, I will update the OP. \$\endgroup\$ Commented May 7, 2012 at 2:13
1
\$\begingroup\$

I'd recommend you to create an specific manager for showing text...

To Add a message:

     MessageSystem.Instance.Show("My string data", Pos, 1);

The Class

public class MessageSystem {

    public static readonly MessageSystem Instance = new MessageSystem();

    struct Message {
        public SpriteFont Font;
        public string Data;
        public Vector2 Pos;
        public float Duration;
        public float Alpha;
        ....
    }

    List<Message> Messages = new List<Message>();

    public void Show(string data, vector2 pos, float Duration = 1, SpriteFont font = DefaultFont, Alpha = 1)
    {
        Messages.Add(new Message() { Data = data, Font = font, Pos = pos, Duration = duration, ...});
    }
    public void Update(float Seconds) {  // == (float) gametime.ElapsedTime.TotalSeconds

       for (int i=0; i<Messages.Length; )
       {
           Message[i].Duration -= Seconds;
           if (Message[i].Duration<0)
           {
              Messges.RemoveAt[i];
              continue;
           }
           i++;
       }
    }


    public void Draw(SpriteBatch batch)
    {
       batch.Begin();
       for (int i=0; i<Messages.Length; )
       {
            batch.DrawString(Message[i].Font, ....)
       }
       batch.end()
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .