Jump to content
  • Advertisement
Sign in to follow this  
miruim

Design and C# Possibilities

This topic is 3407 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a game where I have an Item class. Instead of making each instance of that to belong to only one type like Weapon, Armor, Consumable, Radio, and so on, I'd like to, instead, let each instance of the Item object have multiple "properties". That's because I want to let them be very customizable, and have for example a survival jacket that is also a container, a helmet that has a radio, and so on. What I need is: A class that contains, as one of its elements, a list of properties, each one belonging to a different class (maybe all of them inheriting the same Property class). I thought of: List<Property> myPropertyList = new List<Property>(); And then: ListProperty.Add(new Armor); ListProperty.Add(new Radio); Is that possible to implement in the way explained? How close could I get to implement that sort of thing using C#? Does the "as" keyword need to or is able to be used to any utility here (so the Add() will accept the "heirs" of Property base class)? Thanks!

Share this post


Link to post
Share on other sites
Advertisement
You've stumbled roughly on what most people describe as a component system. The classic paper, at least when applied to games, is Scott Bilas' GDC presentation. Read the first 20 slides or so; after that it shifts into high gear and goes into a lot of in depth advanced technical tricks that are entirely unnecessary for an indie/hobbyist.

Read that first and then we can start taking a look at putting it into practice [smile]

Share this post


Link to post
Share on other sites
That's SO awesome! :P

Specially the part when he talks about what I wanted to do, the component system.

By looking at that I suppose the List<> won't do it, but maybe an object[] or an Array?

I can work out the code and stuff, but I need the idea of which data structures will work best as that is something you know a lot better than me.

Thanks again!

Share this post


Link to post
Share on other sites
No, List<T> works just fine. The way I did this was like so:

public abstract class GoComponent
{
[Browsable(true),
Category("\t\tGeneral"),
Description("The name of this component. Useful for linking or debugging.")]
public string Name
{
get;
set;
}

private GameObject m_parent;

[Browsable(false)]
public GameObject Parent
{
get { return m_parent; }
}

protected virtual void OnAddToObject(GameObject parent)
{
}

protected virtual void OnAddToWorld(GameWorld world)
{
}

protected virtual void OnRemoveFromObject()
{
}

protected virtual void OnRemoveFromWorld(GameWorld world)
{
}

internal void AddToObject(GameObject parent)
{
Debug.Assert(m_parent == null);
Debug.Assert(parent != null);
OnAddToObject(parent);
m_parent = parent;
}

internal void AddToWorld(GameWorld world)
{
Debug.Assert(world != null);
OnAddToWorld(world);
}

internal void RemoveFromObject()
{
Debug.Assert(m_parent != null);
Debug.Assert(Removable);

#if !EDITOR
//Components are removed from the world, then from the object
if(m_parent.World != null)
OnRemoveFromWorld(m_parent.World);
#endif

OnRemoveFromObject();
m_parent = null;
}

internal void RemoveFromWorld(GameWorld world)
{
Debug.Assert(world != null);
OnRemoveFromWorld(world);
}

[Category("\t\tGeneral")]
public virtual bool Removable
{
get
{
return true;
}
}

public virtual IGoComponentTemplate GetTemplate()
{
return null;
}

public virtual void Update(TimeSpan elapsedTime)
{
}

public virtual string ToXml()
{
return "";
}
}

public class GameObject
{
private List<GoComponent> m_components = new List<GoComponent>();

[Category("\t\tGeneral"), Browsable(true),
Description("The name of this game object. Useful for linking or debugging.")]
public string Name { get; set; }

[Browsable(false)]
public GameWorld World { get; private set; }

[Browsable(false)]
public virtual bool IsDead { get { return false; } }

public GameObject()
: this("[No name]")
{
}

public GameObject(string name)
{
this.Name = name;
}

public T QueryComponent<T>() where T : GoComponent
{
foreach(GoComponent component in m_components)
{
T value = component as T;
if(value != null)
return value;
}

return null;
}

public IEnumerable<T> QueryComponents<T>() where T : GoComponent
{
foreach(GoComponent component in m_components)
{
T value = component as T;
if(value != null)
yield return value;
}

yield break;
}

public void AddComponent(GoComponent component)
{
component.AddToObject(this);
#if !EDITOR
if(World != null)
component.AddToWorld(World);
#endif

m_components.Add(component);
}

public void RemoveComponent(GoComponent component)
{
Debug.Assert(component.Removable);
Debug.Assert(m_components.Contains(component));

#if !EDITOR
if(World != null)
component.RemoveFromWorld(World);
#endif
component.RemoveFromObject();
m_components.Remove(component);
}

[Browsable(false)]
public IEnumerable<GoComponent> Components
{
get { return m_components; }
}

internal void ResetComponents(int reserve)
{
m_components = new List<GoComponent>(reserve);
}

protected virtual void OnAddToWorld(GameWorld world)
{
}

protected virtual void OnRemoveFromWorld()
{
}

internal void AddToWorld(GameWorld world)
{
Debug.Assert(this.World == null);
Debug.Assert(world != null);

#if !EDITOR
OnAddToWorld(world);
foreach(GoComponent component in m_components)
{
component.AddToWorld(world);
}
#endif

World = world;
}

internal void RemoveFromWorld()
{
Debug.Assert(this.World != null);

#if !EDITOR
foreach(GoComponent component in m_components)
{
component.RemoveFromWorld(this.World);
}
OnRemoveFromWorld();
#endif

World = null;
}

public virtual void Update(TimeSpan elapsedTime)
{
foreach(GoComponent component in m_components)
{
component.Update(elapsedTime);
}
}

public virtual void Draw(RenderPhase phase)
{
foreach(GoComponent component in m_components)
{
IVisualComponent visual = component as IVisualComponent;
if(visual == null)
continue;

visual.Draw(phase);
}
}

internal virtual string ToXml()
{
string xml = "";
xml += XmlTools.OpenTag("GameObject"); //<GameObject>
xml += XmlTools.WriteValue("name", Name);
xml += XmlTools.OpenTag("Components");
foreach(GoComponent gc in Components)
{
xml += gc.ToXml();
}
xml += XmlTools.CloseTag();
xml += XmlTools.CloseTag(); //</GameObject>
return xml;
}
}


I'm still playing with a lot of the details but hopefully that helps.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!