Editor de grafuri de stari

Votati daca va place site-ul!

Acces lent: Asteptati sa vedeti imaginile
Ecranul principal Auto layout
(asezare automata)

 

Explicatii:

Editorul de grafuri de stari a fost creat pentru grafurile de stari ale AI-ului jocului Silent Hunter 4.
Elementele grafului sunt stari iar arcele sunt tranzitii intre stari.

O tranzitie are mai multe elemente constituente:

  • prioritate
  • conditie
  • actiuni de executat (conteaza ordinea actiunilor)

Conteaza ordinea arcelor care ies dintr-o stare.

Aplicatia deschide fisierele create (in Notepad pentru Silent Hunter III) si salveaza folosind acelasi format. Scrierea datelor in mod text are mai multe avantaje: Aceste fisiere arata in felul urmator:
graph navigator_officer
{
	state Start
	{
		type		initial;
		arc Stalker_Idle
		{
			input		true;
			output		OrderMngInit;
		}
	}
	
	state Stalker_Idle
	{
		arc Stalker_WaitOrder
		{
			prio		2;
			% As result of interface command (camera focus on character)
			input		Camera(on);
			output		EyeballSetTarget(CrtCamera);
			output		PlayAnimIntr(NA_turn_d);
		}
		arc Stalker_ExecuteOrder_Talk
		{
			prio		2;
			input		Order(AnyNavigation);
			output		PlayAnimIntr(NA_confirm);
			output		PlayMsg(ChE_K_,Yes_Sir);
		}	
		...
	}
	...
}

Informatiile de layout in "pagina" sunt salvate intr-un alt fisier (prin serializarea datelor de layout existente la runtime).

Limbaj:

Aplicatia a fost dezvoltata in C# (Visual Studio .Net 2003).

Problema editarii de proprietati a fost rezolvata prin customizarea PropertyGrid-ului din .Net Framework. Avantajele sunt
Libraria de diagrame a fost realizata tot de mine si permite:
Pentru structurarea interfetei utilizator s-a folosit Magic Library v1.7.4 (ultima versiune free). Avantajele sunt:

"Momente de programare:"

CustomTypeDescriptor-ul pentru afisarea colectiei generice de proprietati (inlocuieste reflection-ul):


#regionGenericPropertyCollection_CustomTypeDescriptor

/// <summary>

/// a GenericPropertyCollection that in a PropertyGid displays the inner generic properties instead of the

/// reflection-reachable C# properties

/// </summary>

[Serializable]

public class GenericPropertyCollection_CustomTypeDescriptor : GenericPropertyCollection, ICustomTypeDescriptor

{

          #region ICustomTypeDescriptor Members

 

          public TypeConverter GetConverter()

          {

                   return TypeDescriptor.GetConverter( this, true );

          } 

          EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents()

          {

                   return TypeDescriptor.GetEvents( this, true );

          } 

          public object GetPropertyOwner(PropertyDescriptor pd)

          {

                   return this;

          } 

          public PropertyDescriptorCollection GetProperties(Attribute[] attributes)

          {

                   return this.PropertyDescriptorCollection;

          }

...

}


Apelarea modulului de automatic layout:


public void AutomaticLayout()

{

          GridObjectState[] GridObjects = null;

          GridLink[] GridLinks = null;

 

          foreach( object o in Document )

                   if( o is DGraphState )

                   {

                             (o as DGraphState).GetDataForAutomaticLayout( out GridObjects, out GridLinks );

                             break;

                   }

 

          AutomaticLayoutForm dlg = new AutomaticLayoutForm( GridObjects, GridLinks );

          if( DialogResult.OK == dlg.ShowDialog() )

          {

                   DNodeState s = null;

                   foreach( GridObjectState go in dlg.Grid.Objects )

                   {

                             go.state.Center = go.GridPoint.Position;

                             s = go.state;

                   }

                   s.Parent.Bounds = s.Bounds;

                   CenterAllObjects();

          }

          dlg.Dispose();

}


Lista ordonata pentru Branch & Bound din modulul de automatic layout:


public class LayoutList

{

          public ArrayList List = new ArrayList();

          public Grid Grid;

          public int CurrentIndex = 0;

 

          public LayoutList( Grid g )

          {

                   this.Grid = g;

 

                   List.Add( new GridLayout( g ) );

          }

 

          /// <summary>

          /// return true if the new layout is better. Next MUST NOT be called

          /// </summary>

          /// <param name="L"></param>

          /// <returns></returns>

          public bool Add( GridLayout L )

          {

                   if( L.Cost > Current.Cost /* * 1.00f avoid local solutions*/ )

                             return false;

 

                   foreach( GridLayout gl in List )

                   {

                             if( gl.IsTheSameWith( L ) )

                                      return false;

                   }

 

                   bool equal = false; /// (DateTime.Now.Second % 2) == 1;

 

                   int index = -1;

                   foreach( GridLayout gl in List )

                   {

                             ++ index;

 

                             if( index < CurrentIndex )

                                      continue;

 

                             if( gl.IsTheSameWith( L ) )

                                      return false;

 

                             if( equal ? L.Cost <= gl.Cost : L.Cost < gl.Cost )

                             {

                                      List.Insert( index, L );

                                      return true;

                             }

                   }

 

                   List.Add( L );

                   return false;

          }

 

          public bool Finished

          {

                   get

                   {

                             return CurrentIndex > 0 && CurrentIndex == List.Count - 1;

                   }

          }

 

          public void Next()

          {

                   if( ! Finished )

                             ++ CurrentIndex;

          }

 

          public GridLayout Current

          {

                   get

                   {

                             return (GridLayout) List[CurrentIndex];

                   }

          }

}