La mejor forma de hacer un Table Layout en XNA?

Respondida La mejor forma de hacer un Table Layout en XNA?

  • lunes, 19 de marzo de 2012 0:08
     
     
    bueno, lo que sucede es que estoy haciendo un juego en donde el jugador tendrá una información básica y quiero hacer una barra como la que tienen todos los MMORPG para mostrar ataques y eso. pero me parece que hardcodear el código es algo muy malo, así que me llego la idea de usar botones y alinearlos en la ventana según un layout. esa es la cuestión. como puedo hacer ese layout para yo poner mis elementos es un mejor orden en pantalla?

Todas las respuestas

  • miércoles, 21 de marzo de 2012 10:01
     
     Respondida Tiene código

    Pues yo le echaría un vistazo a las clases de winforms de c# para poder hacerte una idea...

    Yo he atacado el tema varias veces,

    unas de forma generica... 

    otras de forma específica, para lo que necesitaba y punto: 

    en ambas, he empezado definiendo un objeto base llamado "Control", con un padre, una colección de hijos, con un tamaño, una posición y un para de rectángulos para la posición en pantalla y la posición cliente respecto de su padre, y siempre me ha gustado implementar el metodo boxing de CSS, añadiendo rectángulos autocalculados "Marging, Border, Padding" porque luego te da mucho juego.

    despues derivando de "Control" tienes que implementar las clases que necesites, usualmente: "Contenedor, Boton, Label,..."

    La mas importante es "Contenedor", que dispondrá de un método "PerformLayout" o similar, que será el que ordene los controles hijos según le hayas especificado.

    Este es el código de la clase "Control" que hice para el editor de voxeles, no está tan bien como me quedó lo que hice para el Gui, pero creo que está bastante completito... :)

    namespace VoxelEditor
    {
        //--------------------------------------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------------------------------------
        public interface ISelectable
        {
            bool Selected { get; set; }
            event Action<object> SelectedAfterChanged;
            event Action<object> SelectedBeforeChanged;
        }
    
        //--------------------------------------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------------------------------------
        public abstract class Control
        {
            protected float LerpRatio = 0.09f;
    
            public Rectangle Bounds;
    
            public event Action<Control> MouseUp;
            public event Action<Control> MouseClick;
            public event Action<Control> RightMouseClick;
            public event Action<Control> MouseEnter;
            public event Action<Control> MouseLeave;
            public event Action<Control> MouseDown;
            public event Action<Control> MouseRightDown;
    
            Padding border;
            Padding padding;
            Padding margin;
    
            public ObservableCollection<Control> Controls = new ObservableCollection<Control>( );
            public event Action<object> SizeChanged;
    
            public Control Parent { get; private set; }
    
            MouseState ms, old;
    
            public bool Enabled = true;
    
            //--------------------------------------------------------------------------------------------------------------------------
            public Rectangle PaddingBounds
            {
                get
                {
                    return new Rectangle(
                        Bounds.Left + Margin.Left + Border.Left,
                        Bounds.Top + Margin.Top + Border.Top,
                        Bounds.Width - Margin.Left - Margin.Right - Border.Left - Border.Right,
                        Bounds.Height - Margin.Top - Margin.Bottom - Border.Top - Border.Bottom
                        );
                }
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public Rectangle ClientArea
            {
                get
                {
                    return new Rectangle(
                         Bounds.Left + Margin.Left + Border.Left + Padding.Left,
                         Bounds.Top + Margin.Top + Border.Top + Padding.Top,
                         Bounds.Width - Margin.Left - Margin.Right - Border.Left - Border.Right - Padding.Left - Padding.Right,
                         Bounds.Height - Margin.Top - Margin.Bottom - Border.Top - Border.Bottom - Padding.Top - Padding.Bottom
                         );
                }
            }
    
            Color backgroundColor= Color.Transparent;
            Color borderColor= Color.Transparent;
            Color marginColor = Color.Transparent;
    
            protected Color DisabledColor = Color.LightSlateGray;
    
            protected float EnabledColorFactor { get { return Enabled ? 0 : 0.3f; } }
    
            public Color BackgroundColor { get { return Color.Lerp( backgroundColor, DisabledColor, EnabledColorFactor ); } set { backgroundColor = value; } }
            public Color BorderColor { get { return Color.Lerp( borderColor, DisabledColor, EnabledColorFactor ); } set { borderColor = value; } }
            public Color MarginColor { get { return Color.Lerp( marginColor, DisabledColor, EnabledColorFactor ); } set { marginColor = value; } }
            public Color PaddingColor { get { return BackgroundColor; } }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public Size Size
            {
                get { return new Size( ) { Width = Bounds.Width, Height = Bounds.Height }; }
                set
                {
                    Bounds.Width = value.Width;
                    Bounds.Height = value.Height;
    
                    OnSizeChanged( );
                }
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public Size ClientAreaSize
            {
                get { return new Size( ) { Width = ClientArea.Width, Height =  ClientArea.Height }; }
                set
                {
                    Bounds.Width = value.Width+Margin.Left+Margin.Right+Border.Left+Border.Right+Padding.Left +Padding.Right;
                    Bounds.Height = value.Height+Margin.Top+Margin.Bottom+Border.Top+Border.Bottom+Padding.Top +Padding.Bottom;
    
                    OnSizeChanged( );
                }
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public Padding Border
            {
                get { return border; }
                set { border = value; OnSizeChanged( ); }
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public Padding Padding
            {
                get { return padding; }
                set { padding = value; OnSizeChanged( ); }
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public Padding Margin
            {
                get { return margin; }
                set { margin = value; OnSizeChanged( ); }
            }
    
    
            //--------------------------------------------------------------------------------------------------------------------------
    
            public Control( )
            {
                Controls.CollectionChanged+=new System.Collections.Specialized.NotifyCollectionChangedEventHandler( Controls_CollectionChanged );
            }
    
            void Controls_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
            {
                switch ( e.Action )
                {
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
    
                        (e.NewItems[0] as Control).Parent = this;
                        break;
                }
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public virtual void Dispose( )
            {
                MouseUp = MouseClick = RightMouseClick = MouseEnter = MouseLeave = MouseDown = MouseRightDown = null;
                SizeChanged = null;
    
                Controls.CollectionChanged-=new System.Collections.Specialized.NotifyCollectionChangedEventHandler( Controls_CollectionChanged );
                
                foreach ( Control control in Controls )
                {
                    control.Dispose( );
                    control.Parent = null;
                }
               
                Controls.Clear( );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnSizeChanged( )
            {
                if ( SizeChanged!=null )
                    SizeChanged( this );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public virtual void Update( float Seconds )
            {
                if ( Enabled )
                {
                    ms = Mouse.GetState( );
                    UpdateMouse( Seconds );
                    foreach ( Control control in Controls )
                        control.Update( Seconds );
                    old = ms;
                }
            }
    
            protected enum MouseStates { Out, Over };
    
            protected enum DraggingStates { None, BeginDragging, Dragging }
    
            protected MouseStates MouseState;
            protected DraggingStates DraggingState;
    
            protected Vector2 MousePosition, MouseDelta, BeginDraggingPosition;
            float DraggingTime;
    
            private void UpdateMouse( float Seconds )
            {
                MouseDelta.X = ms.X - MousePosition.X;
                MouseDelta.Y = ms.Y - MousePosition.Y;
    
                MousePosition.X = ms.X;
                MousePosition.Y = ms.Y;
                DraggingTime+= Seconds;
    
                switch ( MouseState )
                {
                    case MouseStates.Out:
                        if ( PaddingBounds.Contains( ms.X, ms.Y ) )
                        {
                            MouseState = MouseStates.Over;
                            OnMouseEnter( );
                        }
                        break;
    
                    case MouseStates.Over:
                        if ( !PaddingBounds.Contains( ms.X, ms.Y ) )
                        {
                            MouseState = MouseStates.Out;
                            OnMouseLeave( );
                        }
                        else if ( ms.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed && old.LeftButton == ButtonState.Released )
                        {
                            OnMouseDown( );
                            BeginDraggingPosition = MousePosition;
                            DraggingState = DraggingStates.BeginDragging;
                            DraggingTime = 0;
                        }
                        else if ( ms.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Released && old.LeftButton == ButtonState.Pressed )
                        {
                            OnMouseUp( );
                            if ( DraggingState!= DraggingStates.Dragging )
                                OnMouseClick( );
                        }
                        else if ( ms.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed && old.RightButton == ButtonState.Released )
                        {
                            OnMouseRightDown( );
                        }
                        else if ( ms.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Released && old.RightButton == ButtonState.Pressed )
                        {
                            OnMouseRightClick( );
                        }
    
                        break;
                }
    
                switch ( DraggingState )
                {
                    case DraggingStates.BeginDragging:
                        if ( DraggingTime>0.1f && Vector2.Distance( BeginDraggingPosition, MousePosition )>4 )
                        {
                            DraggingState = DraggingStates.Dragging;
                            OnBeginDragging( );
                        }
                        break;
    
                    case DraggingStates.Dragging:
    
                        if ( ms.LeftButton == ButtonState.Pressed )
                        {
                            OnDragging( );
                        }
                        else
                        {
                            OnEndDragging( );
                            DraggingState = DraggingStates.None;
                        }
                        break;
                }
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnEndDragging( ) { }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnDragging( ) { }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnBeginDragging( ) { }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnMouseUp( )
            {
                if ( MouseUp!=null )
                    MouseUp( this );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnMouseClick( )
            {
                if ( MouseClick!=null )
                    MouseClick( this );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnMouseRightClick( )
            {
                if ( RightMouseClick!=null )
                    RightMouseClick( this );
            }
    
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnMouseEnter( )
            {
                if ( MouseEnter!=null )
                    MouseEnter( this );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnMouseLeave( )
            {
                if ( MouseLeave!=null )
                    MouseLeave( this );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnMouseDown( )
            {
                if ( MouseDown!=null )
                    MouseDown( this );
            }
            //--------------------------------------------------------------------------------------------------------------------------
            protected virtual void OnMouseRightDown( )
            {
                if ( MouseRightDown!=null )
                    MouseRightDown( this );
            }
            
            //--------------------------------------------------------------------------------------------------------------------------
            public virtual void Draw( AdvancedSpriteBatch batch )
            {
                foreach ( Control control in Controls )
                    control.Draw( batch );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public virtual void OnLayoutApplied() { }
        }
    }
    

    Y aqui la clase "Contenedor", no es la mejor forma de hacerlo, pero hace lo que necesitaba...

    //--------------------------------------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------------------------------------
        public enum Layout { DownOnly, LeftOnly, UpToDown, LeftToRight }
    
        //--------------------------------------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------------------------------------
        public class Container: Control
        {
            public ObservableCollection<ContainerBehaviour> Behaviours = new ObservableCollection<ContainerBehaviour>( );
    
            //--------------------------------------------------------------------------------------------------------------------------
            public Container( )
            {
                Behaviours.CollectionChanged+=new System.Collections.Specialized.NotifyCollectionChangedEventHandler( Behaviours_CollectionChanged );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            void Behaviours_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
            {
                switch ( e.Action )
                {
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                        (e.NewItems[0] as ContainerBehaviour).Initialize( this );
                        break;
                }
            }
    
            public override void Draw( AdvancedSpriteBatch batch )
            {
                batch.FillCssRectangle( Bounds, Margin, MarginColor, Border, BorderColor, Padding, PaddingColor, BackgroundColor );
                base.Draw( batch );
            }  
           
        }
    
        //--------------------------------------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------------------------------------
        public abstract class ContainerBehaviour
        {
            protected Container ParentContainer;
    
            //--------------------------------------------------------------------------------------------------------------------------
            public virtual void Initialize( Container parent )
            {
                this.ParentContainer = parent;
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public virtual void Update( float seconds ) { } 
        }
    
        //--------------------------------------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------------------------------------
        public class LayoutProvider: ContainerBehaviour
        {
            public Layout Layout = Layout.LeftOnly;
    
            //--------------------------------------------------------------------------------------------------------------------------
            public override void Initialize( Container parent )
            {
                base.Initialize( parent );
                
                parent.SizeChanged+=( o ) => DoLayout( );
    
                parent.Controls.CollectionChanged+=new System.Collections.Specialized.NotifyCollectionChangedEventHandler( Controls_CollectionChanged );
                foreach ( Control control in parent.Controls )
                    RegisterSizeChanged( control );
                DoLayout( );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            private void RegisterSizeChanged( Control control )
            {
                control.SizeChanged += ( s ) => DoLayout( );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            void Controls_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
            {
                switch (e.Action)
                {
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                        RegisterSizeChanged( e.NewItems[0] as Control ); break;
                }
                DoLayout( );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            public void DoLayout( )
            {
                Rectangle Used;
                Rectangle Bounds = ParentContainer.ClientArea;
              
                Used.X = Bounds.X;
                Used.Y = Bounds.Y;
                Used.Width = Used.Height = 0;
                Size current = Size.Zero;
    
                foreach ( Control b in ParentContainer.Controls )
                {
                    switch ( Layout )
                    {
                        case VoxelEditor.Layout.LeftOnly:
                                b.Bounds.X = Used.Right;
                                b.Bounds.Y = Used.Bottom;
                                Used.Width += b.Bounds.Width;
                                break;
                        
                        case VoxelEditor.Layout.LeftToRight:
    
                            if ( b.Size.Width+Used.Width > Bounds.Width )
                            {
                                Used.Height += current.Height;
                                Used.Width = b.Bounds.Width;
                                b.Bounds.X = Used.X;
                                b.Bounds.Y = Used.Bottom;
                                current.Height = 0;
      
                            }
                            else
                            {
                                b.Bounds.X = Used.Right;
                                b.Bounds.Y = Used.Bottom;
                                Used.Width += b.Bounds.Width;
                            }
    
                            current.Height = Math.Max( current.Height, b.Size.Height );
                            break;
    
                        case VoxelEditor.Layout.DownOnly:
                               b.Bounds.Y = Used.Bottom;
                                b.Bounds.X = Used.Right;
                                Used.Height += b.Bounds.Height;
                                break;
    
                        case VoxelEditor.Layout.UpToDown:
    
                            if ( b.Size.Height+Used.Height > Bounds.Height )
                            {
                                Used.Width += current.Width;
                                Used.Height = b.Bounds.Height;
                                b.Bounds.Y = Used.Y;
                                b.Bounds.X = Used.Right;
                                current.Width = 0;
                            }
                            else
                            {
                                b.Bounds.Y = Used.Bottom;
                                b.Bounds.X = Used.Right;
                                Used.Height += b.Bounds.Height;
                            }
    
                            current.Width = Math.Max( current.Width, b.Size.Width );
                            break;
                    }
    
                    b.OnLayoutApplied( );
    
                    if ( b is Container )
                    {
                        LayoutProvider lp = (b as Container).Behaviours.OfType<LayoutProvider>( ).FirstOrDefault( );
                        if ( lp!=null )
                            lp.DoLayout( );
                    }
    
                }
            }
        }
    
        //--------------------------------------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------------------------------------
        // 
        // Solo un boton puede estar activo a la vez
        // 
        //--------------------------------------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------------------------------------
        public class GroupProvider: ContainerBehaviour
        {
            //--------------------------------------------------------------------------------------------------------------------------
            public override void Initialize( Container parent )
            {
                base.Initialize( parent );
                parent.Controls.CollectionChanged+=new System.Collections.Specialized.NotifyCollectionChangedEventHandler( Controls_CollectionChanged );
                foreach ( ISelectable selectable in parent.Controls.OfType<ISelectable>() )
                    RegisterSelectable( selectable );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            void Controls_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
            {
                switch ( e.Action )
                {
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                        RegisterSelectable( e.NewItems[0] as ISelectable );
                        break;
                }
    
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            private void RegisterSelectable( ISelectable iSelectable )
            {
                if ( iSelectable == null )
                    return;
    
                iSelectable.SelectedAfterChanged+=new Action<object>( Selectable_SelectedAfterChanged );
            }
    
            //--------------------------------------------------------------------------------------------------------------------------
            void Selectable_SelectedAfterChanged( object sender )
            {
                if ( (sender as ISelectable ).Selected )
                {
                    foreach ( ISelectable selectable in ParentContainer.Controls.OfType<ISelectable>( ) )
                    {
                        if ( selectable != sender )
                            selectable.Selected = false;
                    }
                }
            }
        }

    Espero que te sirva de ayuda


    Tambien conocido como Blau www.youtube.com/malditis www.charcostudios.com

  • miércoles, 21 de marzo de 2012 13:33
     
     
    muchas gracias, ya tengo una base de por donde empezar, apenas tenga algo útil del código lo comparto con la comunidad.