views:

208

answers:

4

Hey guys, I am working on a game, and wanted to add a screen that would open when the user clicked on certain objects. The screen would be laid out to have an image on the left, a title on the top right, and text below the title.

I have a few problems with this, 1) How would I create the popup box? (preferably with rounded edges) 2) How would I wrap the text (in front of the picture, but not outside the popup-box, I may even need vertical scroll bars) 3) How would I account for different screen resolutions (would they even make a difference?)

Thanks for any and all help, Max

+1  A: 

I have not touched XNA for years, but I would suggest that you take a look at the Game state sample. It is probably a little dated now, but will give you a good starting point for managing the state of your game and 'Popup Windows', menus etc.

http://creators.xna.com/en-US/samples/gamestatemanagement

Chris Taylor
This is a little to robust for my game, I just need a popup that is part of the gameplay.. example: you click on a house, the popup comes up with a picture of the house, the owner in the title, and a synopses of the house.
mazzzzz
@Mazzzzz - XNA is pretty low-level, there is no built-in stuff like you have in other window frameworks. Thus you have to build most of it yourself or maybe find someone who have made it already. @Chris pointer is a good starting point for building screens, you can probably borrow some techniques for building "windows" in your game.
Peter Lillevold
A: 

You should just look into the sprite batch object, which handles the ui in the game state management example

Lavinski
+2  A: 

the rounded edges etc can be handled best by making an image of what you want the popup to look like and styling it how you want.

lets say that you made a box, 300px by 300px

then from there you would want to wrap your text within, and possibly have it scroll or however you want to handle it by checking the text height and width to find where to wrap the text...

for example you could make a function like this which would take your full text and wrap it based on some measurements.

private string WrapText(string text)
{
  string[] words = text.Split(' ');
  StringBuilder sb = new StringBuilder();
  float linewidth = 0f;
  float maxLine = 250f; //a bit smaller than the box so you can have some padding...etc
  float spaceWidth = spriteFont.MeasureString(" ").X;

  foreach (string word in words)
  {
    Vector2 size = spriteFont.MeasureString(word);
    if (linewidth + size.X < 250)
    {
      sb.Append(word + " ");
      linewidth += size.X + spaceWidth;
    } 
    else
    {
      sb.Append("\n" + word + " ");
      linewidth = size.X + spaceWidth;
    }
  }
  return sb.ToString();
}

if your text is to much for a top to bottom view - you would have to come up with some sort of scrolling text, or a "continue" button press to load the next page of text for example.

finally as far as resolution goes, it depends on the platform, you want to build your game and art towards the platform for example a 300x300 image for a dialog box probably wont work that great if this is something you are building in XNA 4 for a phone, but would be fine for an xbox build, and most logically the pc build. Though with viewports you probably could use the same art (just might be worth it to use smaller images for a much smaller screen.

for resolution kind of questions you probably want to look at some things like tile safe area, and read a bit about viewports. It's also suggested that you set your game to run at 1280 x 720 which is a 720p native resolution that should work on all tvs and gives you a reference for your art.

public Game1()
{
    graphics = new GraphicsDeviceManager(this);

    this.graphics.PreferredBackBufferWidth = 1280;
    this.graphics.PreferredBackBufferHeight = 720;

    Content.RootDirectory = "Content";
}

that should hopefully at least push you in the right direction.

David Larrabee
Thanks a ton! The wrapping is exactly what I was looking for, I just need to find a rounded edges tutorial, and I'm golden!
mazzzzz
+1  A: 

For any looking, here is the complete code I worked up on it, the code is kinda chicken scratch, but it does the job..

Do notice I put the FillText loader inside the main function, you should move this outside (so it doesn't get repeatedly called), if you use this code

        public void DisplayPopup (string Title, string Text, string AssetPicturePath, SpriteBatch batch)
    {
        FillText = new Texture2D(game.GraphicsDevice, 1, 1);
        FillText.SetData(new Color[] { Color.White });
        //Draw rectangle, center screen,
        Rectangle MainBox;
        MainBox.Width = 700;
        MainBox.Height = 400;
        MainBox.X = game.Window.ClientBounds.Width / 2 - MainBox.Width / 2;
        MainBox.Y = game.Window.ClientBounds.Height / 2 - MainBox.Height / 2;

        //Draw Title
        Rectangle TitleBox;
        TitleBox.Width = 650;
        TitleBox.Height = (int)ArialFont.MeasureString(Title).Y;
        Padding = MainBox.Width / 2 - TitleBox.Width / 2;
        TitleBox.X = (int)Padding + MainBox.X;
        TitleBox.Y = (int)Padding + MainBox.Y;

        //Draw Line Between Title and TextBox
        Rectangle TextSeperator;
        TextSeperator.Width = MainBox.Width - (int)Padding * 2;
        TextSeperator.Height = 1;
        TextSeperator.X = MainBox.X + (int)Padding;
        TextSeperator.Y = TitleBox.Y + (int)(Padding * 1.2);

        //Draw PictureBox
        Rectangle PictureBox;
        if (AssetPicturePath != string.Empty)
            PictureBox.Width = 200;
        else
            PictureBox.Width = 0;

        PictureBox.Height = 250;
        PictureBox.X = MainBox.X + (int)Padding;
        PictureBox.Y = MainBox.Y + TitleBox.Height + (int)Padding * 2;

        MainBox.Height = PictureBox.Y - MainBox.Y + PictureBox.Height + (int)Padding;

        //Draw TextBody
        Rectangle TextBody;
        if (AssetPicturePath == string.Empty)
            TextBody.Width = MainBox.Width - ((int)Padding * 2);
        else
            TextBody.Width = MainBox.Width - ((int)Padding * 3) - PictureBox.Width;
        TextBody.Height = MainBox.Height - ((int)Padding * 3) - TitleBox.Height;
        if (AssetPicturePath == string.Empty)
            TextBody.X = PictureBox.X;
        else
            TextBody.X = PictureBox.X + PictureBox.Width + (int)Padding;
        TextBody.Y = TitleBox.Y + TitleBox.Height + (int)Padding;

        //Draw MainBox
        batch.Draw(FillText, MainBox, Color.Wheat);
        //Draw PictureBox
        //batch.Draw(FillText, PictureBox, Color.Green);
        if (AssetPicturePath != string.Empty)
            batch.Draw(game.Content.Load<Texture2D>(AssetPath + AssetPicturePath.TrimStart(new char[] { '/' })), PictureBox, Color.White);
        //Draw TitleBox
        //batch.Draw(FillText, TitleBox, Color.BlueViolet);
        batch.DrawString(ArialFont, Title, new Vector2(TitleBox.X, TitleBox.Y),Color.Blue);
        //Draw Line Between Title And TextBody
        batch.Draw(FillText, TextSeperator, Color.Gray);
        //Draw TextBody
        //batch.Draw(FillText, TextBody, Color.Indigo);
        int LineNumber = 0;
        foreach (string Line in WrapText(Text, TextBody.Width))
        {
            batch.DrawString(ArialFont, Line, new Vector2(TextBody.X, TextBody.Y + (LineNumber * ArialFont.MeasureString(Line).Y)), Color.Black);
            LineNumber++;
        }

    }
    private object[] WrapText(string text, float Length)
    {
        string[] words = text.Split(' ');
        ArrayList Lines = new ArrayList();
        float linewidth = 0f;
        float spaceWidth = ArialFont.MeasureString(" ").X;
        int CurLine = 0;
        Lines.Add(string.Empty);
        foreach (string word in words)
        {
            Vector2 size = ArialFont.MeasureString(word);
            if (linewidth + size.X < Length)
            {
                Lines[CurLine] += word + " ";
                linewidth += size.X + spaceWidth;
            }
            else
            {
                Lines.Add(word + " ");
                linewidth = size.X + spaceWidth;
                CurLine++;
            }
        }
        return Lines.ToArray();
    }
mazzzzz
+1 for completeness.However, ArrayList has been deprecated, you should be using List<string> here.If you were looking to port this code to Windows Phone 7 XNA for example, ArrayList isn't available.
TreeUK