How do I "update" a reference in this situation?

I'm working on a small game engine in C++. I added a system where you can add components (made from an abstract class) to a object to give it functionality. I'm currently working on a new component to give an object a parent so it can follow it when moving.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Parent : Component
{
public:
	bool inheritPosition, inheritRotation, inheritScale;
	glm::vec3 localPosition, localRotation, localScale;
	Object parent;

	Parent(Object &object, Object &parent, bool inheritPos = true, bool inheritRot = true, bool inheritScale = true) : Component(object)
	{
		this->parent = parent;
		this->inheritPosition = inheritPos;
		this->inheritRotation = inheritRot;
		this->inheritScale = inheritScale;
		init(object);
	}

	void init(Object &object)
	{
		//Sets the local transform to the right values
		if(inheritPosition)
			localPosition = parent.transform.position - object.transform.position;
		if(inheritRotation)
			localPosition = parent.transform.rotation - object.transform.rotation;
		if (inheritScale)
			//Need to work out math on this one.
			localScale = glm::vec3(1.0f);
	}

	void update(Object &object)
	{
		//Sets true transform based off local transform

		std::cout << parent.transform.position[0] << std::endl;

		if (inheritPosition)
			object.transform.position = parent.transform.position + localPosition;
		if (inheritRotation)
			object.transform.rotation = parent.transform.rotation + localRotation;
	}
};


note that init and update are overwritten methods from Component. In my example, a box is placed at (2.0, 0.0, 0.0) and has a component that moves it (1.0, 0.0, 0.0) every second. The reference appears to only copy the box at initialization, so the std::cout at the update method is display 2.0 across the board. What I would want is an the reference to be updated every frame, so the child can properly follow the parent. Is there a way for this to be done or should I rework how my components work?
Last edited on
Use a reference (or if the parent may be a different object at different points in time, a pointer).

For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>

struct object { int x = 0 ; int y = 0 ; };

struct A
{
    explicit A( const object& p ) : parent(p) {} // initialise reference

    void show_parent() const
    {
        std::cout << "A: parent object{" << parent.x << ','
                  << parent.y << "} at " << std::addressof(parent) << '\n' ;
    }

    const object& parent ; // reference to parent object
                           // the parent is always the same object
};

struct B
{
    explicit B( const object* pp = nullptr ) : parent(pp) {} // initialise pointer

    void show_parent() const
    {
        if(parent) // if there is a parent
        {
            std::cout << "B: parent object{" << parent->x << ','
                      << parent->y << "} at " << parent << '\n' ;
        }

        else std::cout << "B: no parent object\n" ;
    }

    const object* parent ; // (non-owning) pointer to parent object
                           // the parent may be changed to be a different object
                           // or there may be no parent at all (nullptr)
};

int main()
{
    object x { 123, 456 } ;
    A a(x) ;
    B b( std::addressof(x) ) ;
    a.show_parent() ;
    b.show_parent() ;

    x = { 567, 890 } ; // modify parent
    a.show_parent() ;
    b.show_parent() ;

    object y { -99, -88 } ;
    b = { B( std::addressof(y) ) } ; // change b's parent
    b.show_parent() ;

    b = { B(nullptr) } ; // remove b's parent
    b.show_parent() ;
}

http://coliru.stacked-crooked.com/a/ed0db838b8363777
Last edited on
Hello. It took a bit of trial of error. Being from Java, pointers and references are still very new to me but I'm slowly getting better at them. I adapted struct B to my class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Parent : Component
{
public:
	bool inheritPosition, inheritRotation, inheritScale;
	glm::vec3 localPosition, localRotation, localScale;
	Object* parent;

	Parent(Object &object, Object* parent, bool inheritPos = true, bool inheritRot = true, bool inheritScale = true) : Component(object)
	{
		this->parent = parent;
		this->inheritPosition = inheritPos;
		this->inheritRotation = inheritRot;
		this->inheritScale = inheritScale;
		init(object);
	}

	void init(Object &object)
	{
		//Sets the local transform to the right values
		if(inheritPosition)
			localPosition = parent->transform.position - object.transform.position;
		if(inheritRotation)
			localPosition = parent->transform.rotation - object.transform.rotation;
		if (inheritScale)
			//Need to work out math on this one.
			localScale = glm::vec3(1.0f);
	}

	void update(Object &object)
	{
		//Sets true transform based off local transform

		std::cout << parent->transform.position[0] <<std::endl ;

		if (inheritPosition)
			object.transform.position = parent->transform.position + localPosition;
		if (inheritRotation)
			object.transform.rotation = parent->transform.rotation + localRotation;
	}
};


The class works perfectly, and the only problems left are logic errors which I can solve on my own. Thank you very much!
On a matter of style, it's often considered a bit ropey to use this->. That's necessary if you've passed into a class function (or constructor) a variable with the same name as a member variable. A solution you might consider as an alternative to this-> is to not name the parameters of class functions the same as class member variables.

In many cases, you already don't do that:

1
2
3
4
5
		this->parent = parent;
		this->inheritPosition = inheritPos;
		this->inheritRotation = inheritRot;
		this->inheritScale = inheritScale;
		init(object);

could become
1
2
3
4
5
		this->parent = parent;
		inheritPosition = inheritPos;
		inheritRotation = inheritRot;
		this->inheritScale = inheritScale;
		init(object);

already. Why not go the rest of the way with the other parameter names?
by the way class Parent : Component it's composition, `Parent' has a `Component'
if you want inheritance, is a, you need to write class Parent : public Component
Registered users can post here. Sign in or register to post.