【问题标题】:XNA popup text dialogXNA 弹出文本对话框
【发布时间】:2010-05-16 19:17:10
【问题描述】:

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

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

感谢您的任何帮助, 最大

【问题讨论】:

    标签: c# popup xna word-wrap


    【解决方案1】:

    通过制作您希望弹出窗口的外观并按照您的需要设置样式,可以最好地处理圆形边缘等。

    假设你制作了一个 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 中构建的东西,对话框的 300x300 图像可能不会那么好用4 用于手机,但对于 xbox 构建来说很好,最符合逻辑的是 pc 构建。尽管使用视口,您可能可以使用相同的艺术作品(在更小的屏幕上使用更小的图像可能是值得的。

    对于解决问题,您可能想查看tile safe area 之类的内容,并阅读一些关于viewports 的内容。还建议您将游戏设置为以 1280 x 720 运行,这是 720p 原生分辨率,应该适用于所有电视,并为您的艺术提供参考。

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
    
        this.graphics.PreferredBackBufferWidth = 1280;
        this.graphics.PreferredBackBufferHeight = 720;
    
        Content.RootDirectory = "Content";
    }
    

    希望至少能将你推向正确的方向。

    【讨论】:

    • 感谢您的样品。我用 Maxline 变量替换了你的静态 250f,我将 Maxline 变量更新为 0.8f * Viewport.Width。然后,每当 viewport.width 发生变化时,我都会更新并换行文本。然后我将此文本粘贴到 GameStateManagement 屏幕 MessageBoxScreen.cs 中。感谢分享。 (是的,我写这篇文章很晚了)
    【解决方案2】:

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

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

    【讨论】:

    • 这对我的游戏来说有点健壮,我只需要一个作为游戏一部分的弹出窗口。例如:你点击一个房子,弹出窗口会显示房子的图片,标题中的所有者,以及房子的概要。
    • @Mazzzzz - XNA 相当低级,没有像其他窗口框架那样的内置东西。因此,您必须自己构建大部分内容,或者可能找到已经完成它的人。 @Chris 指针是构建屏幕的一个很好的起点,您可能可以借用一些技术在游戏中构建“窗口”。
    【解决方案3】:

    对于任何人来说,这里是我编写的完整代码,代码有点鸡肋,但它确实可以完成工作..

    请注意我将 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();
        }
    

    【讨论】:

    • +1 表示完整性。但是,ArrayList 已被弃用,您应该在此处使用 List。例如,如果您希望将此代码移植到 Windows Phone 7 XNA,则 ArrayList 不可用。
    【解决方案4】:

    您应该只查看精灵批处理对象,它在游戏状态管理示例中处理用户界面

    【讨论】:

      猜你喜欢
      • 2017-08-03
      • 2011-09-30
      • 2015-09-17
      • 2012-06-07
      • 2012-02-05
      • 1970-01-01
      • 1970-01-01
      • 2021-10-26
      • 2012-01-04
      相关资源
      最近更新 更多