Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
Offline maxthekokusaiwarrior  
#1 Posted : Monday, March 31, 2014 1:09:17 PM(UTC)
maxthekokusaiwarrior

Joined: 11/4/2013(UTC)
Posts: 18

Hi guys Smile

I need some explanations about how to link two or more sprites in order to create a hierarchy. Suppose we have two sprites, called Parent and Child. How can I link the Child sprite to the Parent sprite in order to enstablish a parent-child relationship? I looked for Delta Engine 1.1 code, and I have found the HierarchyEntity2D class and the HierarchyObject2D interface. However, the Sprite class doesn't implement the HierarchyObject2D interface, so how can I link a sprite to another sprite? Perhaps I have to create a new class called HierarchySprite which inherits from Sprite and implements HierarchyObject2D interface? What's the best practice to follow in this case? Thank you very much for your help Smile

Max

Wanna join the discussion?! Login to your forum accountregister a new account. Or Connect via Facebook Twitter Google

Offline maxthekokusaiwarrior  
#2 Posted : Wednesday, April 2, 2014 9:46:31 AM(UTC)
maxthekokusaiwarrior

Joined: 11/4/2013(UTC)
Posts: 18

Please, someone can suggest me a solution? Confused
Offline ollimorp  
#3 Posted : Wednesday, April 2, 2014 5:43:17 PM(UTC)
ollimorp

Joined: 7/22/2013(UTC)
Posts: 13

Thanks: 1 times
Was thanked: 2 time(s) in 2 post(s)
Hi,

although it´s a while ago, using the engine and I only can take a look at the class-structure, my answer won´t be wrong:

You are right. You just have to implement the HierarchyObject2D-Interface.
When I remember correctly, the Sprite´s entity collection don´t represent an fully parent-child connection for drawing. So you have 2 possibilites:
1: you implement the mechanism from scratch
2: you reuse parts functionality, which Sprite got from Entity2D (should be easily possible, when I take a look at the Interface members.

There is another thread with a similar question, but I can´t look for at the moment. Search for the words "composite" or "scene graph"

ollimorp


Offline Benjamin  
#4 Posted : Wednesday, April 2, 2014 7:02:37 PM(UTC)
Benjamin

Medals: Admin

Joined: 8/20/2011(UTC)
Posts: 1,421
Location: Hannover

Thanks: 18 times
Was thanked: 97 time(s) in 92 post(s)
Hi Max,

There are many solutions, it all depends on how you want it. My first idea is to just add the second entity to the first one and then use that first entity to handle both.

Code:

[Test]
public void RenderMainSpriteWithAttachedSubSprite()
{
	var mainSprite = new Sprite(logoMaterial, Rectangle.HalfCentered);
	mainSprite.Add(new Sprite(logoMaterial, Rectangle.FromCenter(0.5f, 0.5f, 0.1f, 0.1f)));
	mainSprite.Start<UpdateClientSpriteOnPositionChange>();
	new Command(Command.Click, position => mainSprite.Center = position);
}

private class UpdateClientSpriteOnPositionChange : UpdateBehavior
{
	public override void Update(IEnumerable<Entity> entities)
	{
		foreach (Entity2D entity in entities)
			entity.Get<Sprite>().Center = entity.Center;
	}
}


Looks a bit cumbersome, but works. Also would have to be adjusted for each case, you might not want to have things centered at the parent entity. Alternatively you could also roll your own entity (e.g. derived from Sprite) and put all the sub objects in there. DeltaEngine.Scenes.Controls.Control does this and handles many of the parent/child and control related issues.

A better idea would be to use HierarchyObject2D as you have already discovered. But as you also noticed Sprite is not derived from HierarchyEntity2D to implement that functionality. I changed that, so Sprites can be used in Hierarchies now :)
Code:

[Test]
public void RenderHierachyEntityWithAttachedSprites()
{
	var mainEntity = new Sprite(logoMaterial, Rectangle.HalfCentered);
	mainEntity.AddChild(new Sprite(logoMaterial, Rectangle.FromCenter(0.3f, 0.3f, 0.1f, 0.1f)));
	new Command(Command.Click, position => mainEntity.Center = position);
}


In addition to deriving Sprite from HierarchyEntity2D I also had to change some minor things in HierarchyEntity2D to fix the centering. Please note that each entity is created with its own Center position, but when adding it the LocalPosition (now called RelativePosition) is calculated to the parent. Of course you can also set it afterwards.

A new nightly release is coming later this week. If you want to fix it yourself for now:
Code:

public class HierarchyEntity2D : Entity2D, HierarchyObject2D
{
	protected HierarchyEntity2D()
		: this(Rectangle.Zero) {}

	public HierarchyEntity2D(Vector2D position)
		: this(Rectangle.FromCenter(position, Size.Zero)) {}

	public HierarchyEntity2D(Rectangle drawArea, float orientation = 0.0f)
		: base(drawArea)
	{
		Children = new List<HierarchyObject2D>();
		Rotation = orientation;
		localPosition = Vector2D.Zero;
		localRotation = 0;
	}

	public Vector2D LocalPosition
	{
		get { return localPosition; }
		set
		{
			localPosition = value;
			UpdateGlobalsFromParent(Parent);
		}
	}

	private Vector2D localPosition;

	public float LocalRotation
	{
		get { return localRotation; }
		set
		{
			localRotation = value;
			UpdateGlobalsFromParent(Parent);
		}
	}

	private float localRotation;

	public HierarchyObject2D Parent { get; private set; }

	public List<HierarchyObject2D> Children { get; private set; }

	public void Add(HierarchyObject2D child)
	{
		Children.Add(child);
		child.UpdateGlobalsFromParent(this);
	}

	public void Remove(HierarchyObject2D child)
	{
		Children.Remove(child);
		child.UpdateGlobalsFromParent(null);
	}

	public void UpdateGlobalsFromParent(HierarchyObject2D parent)
	{
		if (Parent != parent)
		{
			Parent = parent;
			if (parent != null)
			{
				localPosition = Center - parent.Center;
				localRotation = Rotation - parent.Rotation;
			}
		}
		if (parent == null)
		{
			Center = localPosition;
			Rotation = localRotation;
			return;
		}
		Center = parent.Center + localPosition;
		Rotation = parent.Rotation + localRotation;
		foreach (var child in Children)
			child.UpdateGlobalsFromParent(this);
	}

	public object GetFirstChildOfType<T>() where T : HierarchyObject2D
	{
		for (int i = 0; i < Children.Count; i++)
			if (Children[i].GetType() == typeof(T))
				return (T)Children[i];
		return null;
	}

	protected override void OnPositionChanged()
	{
		UpdateChildren();
		base.OnPositionChanged();
	}

	protected override void OnRotationChanged()
	{
		UpdateChildren();
		base.OnRotationChanged();
	}

	private void UpdateChildren()
	{
		foreach (var child in Children)
			child.UpdateGlobalsFromParent(this);
	}

	public override bool IsActive
	{
		get { return base.IsActive; }
		set
		{
			foreach (var child in Children)
				child.IsActive = value;
			base.IsActive = value;
		}
	}
}
Offline maxthekokusaiwarrior  
#5 Posted : Thursday, April 3, 2014 12:15:08 AM(UTC)
maxthekokusaiwarrior

Joined: 11/4/2013(UTC)
Posts: 18

Hi Benjamin and ollimorp

thank you for this super-explanation :)

Max
Rss Feed  Atom Feed
Users browsing this topic
OceanSpiders 2.0
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Powered by YAF.NET | YAF.NET © 2003-2018, Yet Another Forum.NET
This page was generated in 0.122 seconds.