XNA 弹出文本对话框

发布于 2024-09-01 22:19:47 字数 208 浏览 9 评论 0原文

大家好,我正在开发一款游戏,想要添加一个当用户单击某些对象时会打开的屏幕。屏幕的布局将在左侧显示图像,在右上角显示标题,在标题下方显示文本。

我对此有一些问题, 1)如何创建弹出框? (最好有圆边) 2)我如何将文本换行(在图片前面,但不在弹出框之外,我什至可能需要垂直滚动条) 3)我将如何解释不同的屏幕分辨率(它们甚至会产生影响吗?)

感谢您的所有帮助, 最大限度

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

怪异←思 2024-09-08 22:19:47

圆角边缘等可以通过制作您想要弹出窗口的外观的图像并按照您想要的样式进行设计来最好地处理。

假设您制作了一个 300 像素 x 300 像素的盒子,

那么您希望将文本包裹在其中,并且可能让它滚动,或者您想通过检查文本高度和宽度来找到文本包裹的位置来处理它。 ..

例如,您可以创建一个像这样的函数,它将获取您的全文并根据一些测量结果对其进行换行。

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

如果您的文本对于从上到下的视图来说太多 - 您将不得不想出某种滚动文本,或者按下“继续”按钮来加载下一页文本。

最后,就分辨率而言,这取决于平台,您想要针对该平台构建游戏和艺术,例如,如果这是您在 XNA 4 中构建的用于对话框的 300x300 图像,则可能效果不佳。手机,但对于 Xbox 版本来说就很好了,最合逻辑的是 PC 版本。尽管使用视口,您可能可以使用相同的艺术(在更小的屏幕上使用较小的图像可能是值得的。

对于分辨率类型的问题,您可能想要查看一些东西,例如 平铺安全区域,并阅读一些有关 视口。还建议您将游戏设置为以 1280 x 720 运行,这是一个 720p 的原生分辨率,应该适用于所有电视,并为您提供参考希望

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

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

    Content.RootDirectory = "Content";
}

这至少能推动你走向正确的方向。

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.

原来是傀儡 2024-09-08 22:19:47

我已经很多年没有接触 XNA 了,但我建议您看一下游戏状态示例。它现在可能有点过时,但将为您提供一个管理游戏状态和“弹出窗口”、菜单等的良好起点。

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

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

ら栖息 2024-09-08 22:19:47

对于任何人来说,这里是我编写的完整代码,该代码有点鸡毛蒜皮,但它完成了工作。

请注意,我将 FillText 加载器放在主函数内,您应该将其移到外面(所以它不会不会被重复调用),如果您使用此代码

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

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();
    }
软糯酥胸 2024-09-08 22:19:47

您应该只查看 sprite 批处理对象,它处理游戏状态管理示例中的 ui

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文