【发布时间】:2016-03-04 00:11:44
【问题描述】:
我一直在为我的游戏制作 GUI。到目前为止,我已经使用代码创建了看起来像“表单”的对象(不要与 winforms 混淆,我使用的是 monogame)。我还创建了按钮。但现在我很难创建一个复选框。所以这是我的CheckBoxGUI 课程:
// take a look into the recent edits for this post if you need to see my old code.
我的TextOutliner 类用于绘制带边框/轮廓的文本:
// take a look into the recent edits for this post if you need to see my old code.
最后,这是我在TitleScreen 中使用CheckBoxGUI 类的方法:
// take a look into the recent edits for this post if you need to see my old code.
这是我的问题(至少我认为是这样,在处理复选框逻辑的方法中):
// take a look into the recent edits for this post if you need to see my old code.
最后,Draw():
// take a look into the recent edits for this post if you need to see my old code.
所以CheckBoxInputTS 方法允许我通过单击鼠标来选中/取消选中 CheckBoxGUI 项目,但我实际上无法为其附加任何功能。例如,我可以在同一方法中执行以下操作:
// take a look into the recent edits for this post if you need to see my old code.
也许我遗漏了一些简单的东西,或者我不明白如何实际对代码进行进一步改进,我已经必须使其支持checkBoxes 的不同功能......但是,当我测试这个时,如果我打开窗户并选中该框,窗户就会关闭并且不会再次打开。 WindowGUI 类的 IsOpen 成员通过类的 Draw() 方法中的 if 语句控制窗口是否可见。
如果我尝试对复选框使用其他示例,也会发生同样的事情...一旦checkBox.IsChecked 具有用户给定的值,我就无法更改它。
如果有人能发现我做错了什么并帮助我清理这段代码,我们将不胜感激。提前致谢!
编辑:这是我目前所拥有的,基于建议的答案:
public class CheckBoxGUI : GUIElement
{
Texture2D checkBoxTexEmpty, checkBoxTexSelected;
public Rectangle CheckBoxTxtRect { get; set; }
public Rectangle CheckBoxMiddleRect { get; set; }
public bool IsChecked { get; set; }
public event Action<CheckBoxGUI> CheckedChanged;
public CheckBoxGUI(Rectangle rectangle, string text, bool isDisabled, ContentManager content)
: base(rectangle, text, isDisabled, content)
{
CheckBoxTxtRect = new Rectangle((Bounds.X + 19), (Bounds.Y - 3), ((int)FontName.MeasureString(Text).X), ((int)FontName.MeasureString(Text).Y));
CheckBoxMiddleRect = new Rectangle((Bounds.X + 16), Bounds.Y, 4, 16);
if (checkBoxTexEmpty == null) checkBoxTexEmpty = content.Load<Texture2D>(Game1.CheckBoxPath + @"0") as Texture2D;
if (checkBoxTexSelected == null) checkBoxTexSelected = content.Load<Texture2D>(Game1.CheckBoxPath + @"1") as Texture2D;
}
public void OnCheckedChanged()
{
var h = CheckedChanged;
if (h != null)
h(this);
}
public override void UnloadContent()
{
base.UnloadContent();
if (checkBoxTexEmpty != null) checkBoxTexEmpty = null;
if (checkBoxTexSelected != null) checkBoxTexSelected = null;
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
if (!Game1.IsSoundDisabled)
{
if ((IsHovered) && (!IsDisabled))
{
if (InputManager.IsLeftClicked())
{
ClickSFX.Play();
IsHovered = false;
}
}
}
if (IsClicked) OnCheckedChanged();
}
public void Draw(SpriteBatch spriteBatch)
{
if ((FontName != null) && ((Text != string.Empty) && (Text != null)))
{
if (IsChecked) spriteBatch.Draw(checkBoxTexSelected, Bounds, Color.White);
else if (IsDisabled) spriteBatch.Draw(checkBoxTexEmpty, Bounds, Color.Gray);
else spriteBatch.Draw(checkBoxTexEmpty, Bounds, Color.Gray);
TextOutliner.DrawBorderedText(spriteBatch, FontName, Text, CheckBoxTxtRect.X, CheckBoxTxtRect.Y, ForeColor);
}
}
}
然后是GUIElement 类:
public abstract class GUIElement
{
protected SpriteFont FontName { get; set; }
protected string Text { get; set; }
protected SoundEffect ClickSFX { get; set; }
public Rectangle Bounds { get; set; }
public Color ForeColor { get; set; }
public Color BackColor { get; set; }
public bool IsDisabled { get; set; }
public bool IsHovered { get; set; }
public bool IsClicked { get; set; }
public GUIElement(Rectangle newBounds, string newText, bool isDisabled, ContentManager content)
{
Bounds = newBounds;
Text = newText;
IsDisabled = isDisabled;
FontName = Game1.GameFontSmall;
ForeColor = Color.White;
BackColor = Color.White;
ClickSFX = content.Load<SoundEffect>(Game1.BGSoundPath + @"1") as SoundEffect;
}
public virtual void UnloadContent()
{
if (Bounds != Rectangle.Empty) Bounds = Rectangle.Empty;
if (FontName != null) FontName = null;
if (Text != string.Empty) Text = string.Empty;
if (ClickSFX != null) ClickSFX = null;
}
public virtual void Update(GameTime gameTime)
{
if (!IsDisabled)
{
if (Bounds.Contains(InputManager.MouseRect))
{
if (InputManager.IsLeftClicked()) IsClicked = true;
ForeColor = Color.Yellow;
IsHovered = true;
}
else if (!Bounds.Contains(InputManager.MouseRect))
{
IsHovered = false;
ForeColor = Color.White;
}
}
else ForeColor = Color.Gray;
}
}
这是我的用法:
// Fields
readonly List<GUIElement> elements = new List<GUIElement>();
CheckBoxGUI chk;
bool check = true;
string text;
// LoadContent()
chk = new CheckBoxGUI(new Rectangle(800, 200, 16, 16), "Hide FPS", false, content);
chk.CheckedChanged += cb => check = cb.IsChecked;
elements.Add(chk);
// UnloadContent()
foreach (GUIElement element in elements) element.UnloadContent();
// Update()
for (int i = 0; i < elements.Count; i++) elements[i].Update(gameTime);
foreach (CheckBoxGUI chk in elements) chk.Update(gameTime);
// Draw()
if (chk.IsChecked) check = true;
else check = false;
if (check) text = "True";
else text = "False";
spriteBatch.DrawString(Game1.GameFontLarge, text, new Vector2(800, 400), Color.White);
if (optionsWindow.IsOpen) chk.Draw(spriteBatch);
【问题讨论】:
-
公开一个事件并挂钩它?
-
抱歉,我从来没有接触过高级的面向事件的编程。我已经将 win 表单用于简单的事情,但我从来没有实际需要处理事件,(当然,直到现在)除了 winforms 的预定义的,所以我从来没有学过它们......
-
然后在谷歌上搜索一下事件如何运作的教程,事件将成为你的下一个最好的朋友,它会改变你看待事物的方式;)
-
另外,如果您使用表单,所有这些都是事件,单击、鼠标移动等,也许您知道它们但不知道它们是事件。
-
我确信事件将有助于清理我代码中的所有
bool混乱......但首先我必须学习它们。 @Gusman 我知道它们是事件,我只是从未涉足高级的东西,例如创建自己的事件!我刚开始制作自己的 GUI 对象。