绘制一个文本框,内部剪切文本

时间:2011-10-30 16:51:27

标签: c# textbox xna

如果它很重要,我正在使用XNA 3.1,虽然如果4.0有很大帮助我可以考虑移动。

我正在尝试在游戏中绘制一个文本框。我希望能够只在文本框中显示文本(这样如果字符串更长,在文本框的边缘只显示部分字符)。

我遇到的问题是文本没有被剪裁,在这种情况下它只是在文本框的边界之外进行,或者使用这里描述的建议 - http://social.msdn.microsoft.com/forums/en-US/xnagamestudioexpress/thread/9c395c84-2257-4103-b75c-d9378425cc09 - 我发现如果我使用代码:

spriteBatch.GraphicsDevice.RenderState.ScissorTestEnable = true;
spriteBatch.GraphicsDevice.ScissorRectangle = myTextBox.GetRectangle();

我可以完全按照我的意愿在文本框中剪切它,但不幸的是,它根本没有在游戏中显示任何其他内容!建议使用ScissorRectangle的帖子说它需要在每个SpriteBatch上完成。这让我认为我需要一个新的SpriteBatch。我尝试使用现有的图形设备(新的SpriteBatch(spriteBath.GraphicsDevice))创建一个新的spriteBatch,然后修改它,但由于它是一个引用它有同样的问题,所以我觉得我需要克隆SpriteBatch或GraphicsDevice以某种方式对象,或创建一个新的GraphicsDevice(我不知道在后者的参数中放什么)。克隆方法不可用,有些东西告诉我,我有点复杂,所以这就是为什么我把所有这些背景都放在了。

如果我想显示带有剪切文本的文本框,那么这个ScissorRectangle的新SpriteBatch是最好的前进方式(它似乎运行良好),如果是这样,我该如何获得一个新的SpriteBatch以便我可以只显示我的文本框剪辑,但游戏的其余部分绘制得很好吗?我尝试在创建主游戏的同时创建一个新的spritebatch,但因为GraphicsDevice必须是相同的,所以我无法改变它,所以一个改变而另一个没有。

非常感谢。如果我错过了任何有用的细节,请告诉我 - 此时我不知道可能相关的内容。

4 个答案:

答案 0 :(得分:3)

SpriteBatch并非“拥有”该特定GraphicsDeviceGraphicsDevice由游戏中的所有图形资源共享(这就是 设备的原因)。一般来说,应该只有GraphicsDevice的一个实例。

因此,当您开启剪刀测试时,您正在启用所有SpriteBatch个对象。

答案很简单:再次关闭它!

你是正确的,你需要在一个单独的精灵批处理中执行此操作 - 它不需要是一个单独的SpriteBatch对象!只是一个单独的Begin() / End()块(这是“批处理”)。

更改SpriteBatch在4.0版之前的XNA中使用的渲染状态有点棘手。 SpriteBatch ScissorTestEnable修改了哪些内容。请注意,SpriteBatch不是其中之一,因此应将其设置为之外。

这是因为End可以在调用GraphicsDevice之前对绘图进行排队 - 因此您对Draw进行状态更改并在单个内部调用SpriteBatch批处理的顺序可能与您预期的顺序不同。

Begin() 管理的状态需要在XNA 4.0之前的版本中进行不同的修改。这有点难看。你必须SpriteSortMode.Immediate {{1}然后然后进行更改。)

在XNA 4.0中,您可以将RasterizerState ScissorTestEnable设置为每个批次的Begin()调用所需的值。理解它会容易得多。

答案 1 :(得分:2)

你不需要新的spritebatch ......

也许你没有禁用scissortest ...

要绘制剪辑文本,您必须执行与此类似的操作:

  spriteBatch.GraphicsDevice.RenderState.ScissorTestEnable = true;
  spriteBatch.GraphicsDevice.ScissorRectangle = myTextBox.GetRectangle();
  spriteBacth.Begin();
  spriteBatch.DrawString(...);       
  spriteBacth.End();
  spriteBatch.GraphicsDevice.RenderState.ScissorTestEnable = false;      

它也可以用模板缓冲区来完成,但是有点棘手......

这是我使用模板进行的实施测试:http://www.youtube.com/watch?v=-xUMC7sPAx0

这是剪刀测试的gui实现:http://www.youtube.com/watch?v=3pakgHjnScs

答案 2 :(得分:1)

有一个名为“Sprite batching”的概念和“spritebatch”对象。虽然两者密切相关,但我认为你误解了对象的概念。

具体来说,当你spritebatch.Begin并直到你spritebatch.End你创建(至少)1精灵批处理。此批次的许多设置可以设置为与您可能创建的任何其他批次不同的值。

如果你想创建更多的批次,你只需要更多的spritebatch.Begin ... .End序列。

在这种情况下,由于剪辑是一个精灵批处理效果,你必须在一个或多个构造(.Begin)和终止(.End)的批次中发送要剪切的所有内容 - 并将它们分别从任何批次发送其他批次你不想被剪裁。

简而言之,你最有可能:

  • 渲染你的世界(一个精灵批处理)
  • 渲染您的HUD(另一个甚至可能是同一批次)
  • 设置剪裁蒙版以用于...
  • 渲染剪裁区域(文本)
  • 取消设置剪贴蒙版(因为否则下次调用“绘图”时仍会设置)

这里希望这有助于您理解给予您的建议。

答案 3 :(得分:0)

您可以考虑使用RenderTarget2D将文本渲染为Texture2D,然后使用

只渲染此纹理的一部分
  

SpriteBatch.Draw(Texture2D纹理,矩形目标,矩形源,颜色)

有关如何使用RenderTarget2D的更多信息,请查看以下链接: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.rendertarget%28v=xnagamestudio.31%29.aspx

顺便说一句,完全值得切换到XNA 4.0 - 某些方法只有轻微的语法更改,但整体改进很棒。