2012-02-18 86 views
4

我想知道是否有人能告诉我在XNA创建按钮的简单方法。如何制作简单的XNA按钮?

优选的方式其点击时添加一个功能,和一种方式来添加和容易地除去它们。

+0

按钮是不超过点击在屏幕上的任何不同的精灵。你可以创建一个事件驱动的系统,但这是一个非常窗口的方式来看待它。基本上做一个按钮,你可以在屏幕上绘制一个像图像这样的按钮,然后检测该区域内是否发生点击。这就是关于它的一切。你有没有想要沿着事件驱动路线走下去的原因? – 2012-02-19 03:35:51

+0

你如何添加回调到你的按钮? – Kokodoko 2015-03-15 18:50:54

+0

@Kokodoko你可以将一个动作传递给你的按钮,并在按下时调用它。 – Cyral 2015-03-15 19:08:06

回答

1

我建议使用NeoForce Controls Library来解决GUI相关的问题 - 它包含按钮,以及其他有用的GUI控件,包括弹出窗口,列表视图,组合框等等。

如果你正在写的学习经历一个按钮类......好吧,试着寻求帮助之前,学习通过谷歌更多关于它自己。

附录

这是一些代码,我已经为按钮写。也许它可以作为一个起点。我在我的2D游戏引擎中使用它,所以它已经过调试和测试。

/// <summary> 
/// A control that changes appearance when it is hovered over and triggers some effect when it is clicked 
/// </summary> 
public class EnigmaButton 
{ 
    /// <summary> 
    /// The method signature for notification when a button is clicked 
    /// </summary> 
    /// <param name="sender">EnigmaButton that was clicked</param> 
    public delegate void OnClickEvent(EnigmaButton sender); 

    /// <summary> 
    /// Types of textures used for Enigma Buttons 
    /// </summary> 
    public enum TextureType { Normal, Over, Press } 

    #region Variables 
protected IVisualExposer m_ui; 
protected Rectangle m_bounds; 
    IInputExposer m_input; 
    bool m_over = false, m_press = false, m_wasPressed = false; 

    Dictionary<TextureType, EnigmaResource<Texture2D>> m_textures; 
    string m_text, m_name; 
    EnigmaResource<SpriteFont> m_font; 
    int m_minTextShadow, m_maxTextShadow; 
    Color m_textTint; 

    public event OnClickEvent OnClick; 
    #endregion 

    /// <summary> 
    /// A control that changes appearance when it is hovered over and triggers some effect when it is clicked 
    /// </summary> 
    /// <param name="ui">Graphical assets</param> 
    /// <param name="input">Input exposer for mouse input and XBox controller input</param> 
    /// <param name="reader">XMLReader for the definition of the controller</param> 
    /// <param name="pos">Bounds of the controller</param> 
    public EnigmaButton(IVisualExposer ui, IInputExposer input, XmlReader reader, Rectangle pos) 
    { 
    m_ui = ui; 
    m_bounds = pos; 
     m_textures = new Dictionary<TextureType, EnigmaResource<Texture2D>>(); 
     m_input = input; 
     Enabled = true; 

     #region Reading 
     string name; 
     bool started = false, insideText = false; 

     while (reader.Read()) 
     { 
      if (reader.MoveToContent() == XmlNodeType.Element) 
      { 
       name = reader.Name.ToLower(); 
       if (name == "button") 
       { 
        if (started) 
         throw new Exception("Already started."); 
        started = true; 

        m_name = reader.GetAttribute("name") ?? string.Empty; 
       } 
       else if (!started) 
        throw new Exception("Not started"); 
       else if (name == "text") 
       { 
        m_font = new EnigmaResource<SpriteFont>(); 
        m_font.Filepath = reader.GetAttribute("font"); 

        string minShadow = reader.GetAttribute("minShadow"), maxShadow = reader.GetAttribute("maxShadow"); 
        m_minTextShadow = minShadow != null ? int.Parse(minShadow) : 0; 
        m_maxTextShadow = maxShadow != null ? int.Parse(maxShadow) : 2; 

        m_text = reader.GetAttribute("text") ?? string.Empty; 
        insideText = true; 
        m_textTint = Color.White; 
       } 
       else if (name == "bounds") 
       { 
        insideText = false; 
        m_bounds = new Rectangle(int.Parse(reader.GetAttribute("x")), int.Parse(reader.GetAttribute("y")), 
         int.Parse(reader.GetAttribute("width")), int.Parse(reader.GetAttribute("height"))); 
       } 
       else if (name == "texture") 
       { 
        insideText = false; 
        TextureType texType = (TextureType)Enum.Parse(typeof(TextureType), reader.GetAttribute("type")); 
        if (m_textures.ContainsKey(texType)) 
         throw new Exception("A texture of type '" + texType.ToString() + "' cannot be registered twice"); 
        EnigmaResource<Texture2D> res = new EnigmaResource<Texture2D>(); 
        res.Filepath = reader.ReadString(); 
        m_textures.Add(texType, res); 
       } 
       else if (name == "tint") 
       { 
        if (!insideText) 
         throw new Exception("Tints can only be for text"); 

        float a, r, g, b; 
        string[] split = reader.ReadString().Split(','); 
        if (split.Length != 4) 
         throw new Exception("Colors must be RGBA"); 
        r = float.Parse(split[0].Trim()); 
        g = float.Parse(split[1].Trim()); 
        b = float.Parse(split[2].Trim()); 
        a = float.Parse(split[3].Trim()); 

        m_textTint = new Color(r, g, b, a); 
       } 
      } 
     } 
     #endregion 

     if (!m_textures.ContainsKey(TextureType.Normal)) 
      throw new Exception("A button must have at least a '" + TextureType.Normal.ToString() + "' texture"); 
    } 

    #region Methods 
    public void Initialize() 
    { 
    } 

    public void LoadContent() 
    { 
     EnigmaResource<Texture2D> res; 
     for (int i = 0; i < m_textures.Count; i++) 
     { 
      res = m_textures[m_textures.ElementAt(i).Key]; 
      res.Resource = m_ui.Content.Load<Texture2D>(res.Filepath); 
      m_textures[m_textures.ElementAt(i).Key] = res; 
     } 

     if (m_font.Filepath != null) 
      m_font.Resource = m_ui.Content.Load<SpriteFont>(m_font.Filepath); 
    } 

    public void Update(GameTime gameTime) 
    { 
     m_wasPressed = m_press; 
     m_over = m_bounds.Contains(m_input.MouseX, m_input.MouseY); 
     m_press = m_over ? m_wasPressed ? m_input.IsMouseLeftPressed || m_input.IsButtonPressed(Buttons.A) : m_input.IsMouseLeftTriggered || m_input.IsButtonTriggered(Buttons.A) : false; 
     if (!m_wasPressed && m_press && OnClick != null) 
      OnClick(this); 
    } 

    public void Draw(GameTime gameTime) 
    { 
     Texture2D toDraw = m_textures[TextureType.Normal].Resource; 
     if (Enabled) 
     { 
      if (m_press && m_textures.ContainsKey(TextureType.Press)) 
       toDraw = m_textures[TextureType.Press].Resource; 
      else if (m_over && m_textures.ContainsKey(TextureType.Over)) 
       toDraw = m_textures[TextureType.Over].Resource; 
     } 
     m_ui.SpriteBatch.Draw(toDraw, m_bounds, Enabled ? Color.White : Color.Gray); 

     if (m_font.Resource != null) 
     { 
      Vector2 pos = new Vector2(m_bounds.X, m_bounds.Y); 
      Vector2 size = m_font.Resource.MeasureString(m_text); 
      pos.X += (m_bounds.Width - size.X)/2; 
      pos.Y += (m_bounds.Height - size.Y)/2; 
      UIHelper.DrawShadowedString(m_ui, m_font.Resource, m_text, pos, m_textTint, m_minTextShadow, m_maxTextShadow); 
     } 
    } 
    #endregion 

    #region Properties 
    /// <summary> 
    /// Gets or sets the name of the button 
    /// </summary> 
    public string Name 
    { 
     get { return m_name; } 
     set { m_name = value ?? m_name; } 
    } 

    /// <summary> 
    /// Gets or sets the text drawn in the button. 
    /// WARNING: Will overflow if the text does not normally fit. 
    /// </summary> 
    public string Text 
    { 
     get { return m_text; } 
     set { m_text = value ?? string.Empty; } 
    } 

    /// <summary> 
    /// Gets or sets the bounds of the button 
    /// </summary> 
    public Rectangle Bounds 
    { 
     get { return m_bounds; } 
     set { m_bounds = value; } 
    } 

    /// <summary> 
    /// Whether or not the control is enabled 
    /// </summary> 
public bool Enabled { get; set; } 
    #endregion 
} 
+0

标识见过NeoForce,但dosent似乎喜欢那种我需要在这里的事情,我已经发现了按钮的一些例子在线,但没有过什么我还想。生病可能只是写我自己的类,但任何信息,将不胜感激。 – Cyral 2012-02-18 18:07:12

+0

好的;我在我的答案中添加了一些示例代码。这是一个简化,因为我扁平它继承的层次。 – GGulati 2012-02-19 03:27:10

+0

谢谢,我会研究它。 – Cyral 2012-02-19 12:58:43