I have another problem with my game engine. I'm trying to implement a component system, but I can't get it to work. I have a base component class that's empty and a RenderComponent class that inherits from it and adds a char* called text. When I try to change the value of the char* I get this error:
error C2039: 'text' : is not a member of 'SE::Component'
This is because your 'getComponent' function returns a Component object, not a RenderComponent, so you can only access the Component section of renderComponent.
You could fix this by casting it as a RenderComponent as such
The only problem is type checking, if you cast the component without knowing the type, bad thing's can happen. In mine i have a type variable so i can check the type before a cast(but i never like to do this and i haven't done it at all in my engine so far), but all my component's also inherit from an abstract base class which defines the functions i'll need. Then i just work my distinct components into the limitations of the base class meaning every component will have those functions.
Welcome to having no runtime type-identification and no metatdata in a statically compiled language.
Even the Unity Engine requires you cast its components down when using the generic "getComponent()" function. You have a few options:
1) deal with it
2) activate runtime-type identification and down cast before returning the component in your getComponent() (bad idea)
3) give your Entity class getRenderComponent(), getCollisionComponent(), and get methods returning specific types
4) template your getComponent method to return a specific component depending on the type (essentially the same as above with syntactic candy).
Personally, in ES, we use method #3. I know it seems counterintuitive, as you are no longer able to dynamically add components that weren't part of the engine, but that's not quite the case with ES. Every user-defined component inherits from "Behavior" (which inherits from "Component"). So we are able to hardcode get functions for components that are part of the engine then use down-casting with getBehavior for user-defined components that were added at run-time.
GyroVorbis wrote:Welcome to having no runtime type-identification and no metatdata in a statically compiled language.
Even the Unity Engine requires you cast its components down when using the generic "getComponent()" function. You have a few options:
1) deal with it
2) activate runtime-type identification and down cast before returning the component in your getComponent() (bad idea)
3) give your Entity class getRenderComponent(), getCollisionComponent(), and get methods returning specific types
4) template your getComponent method to return a specific component depending on the type (essentially the same as above with syntactic candy).
Personally, in ES, we use method #3. I know it seems counterintuitive, as you are no longer able to dynamically add components that weren't part of the engine, but that's not quite the case with ES. Every user-defined component inherits from "Behavior" (which inherits from "Component"). So we are able to hardcode get functions for components that are part of the engine then use down-casting with getBehavior for user-defined components that were added at run-time.
Hmm, I never thought about using a template on that method... That's a great idea though :D.
But just to do a bit of prodding; So your Behavior class is just a base for scripted components? Or for statically compiled code that's separate for the engine? Or perhaps both ?
GyroVorbis wrote:Welcome to having no runtime type-identification and no metatdata in a statically compiled language.
Even the Unity Engine requires you cast its components down when using the generic "getComponent()" function. You have a few options:
1) deal with it
2) activate runtime-type identification and down cast before returning the component in your getComponent() (bad idea)
3) give your Entity class getRenderComponent(), getCollisionComponent(), and get methods returning specific types
4) template your getComponent method to return a specific component depending on the type (essentially the same as above with syntactic candy).
Personally, in ES, we use method #3. I know it seems counterintuitive, as you are no longer able to dynamically add components that weren't part of the engine, but that's not quite the case with ES. Every user-defined component inherits from "Behavior" (which inherits from "Component"). So we are able to hardcode get functions for components that are part of the engine then use down-casting with getBehavior for user-defined components that were added at run-time.
Hmm, I never thought about using a template on that method... That's a great idea though :D.
But just to do a bit of prodding; So your Behavior class is just a base for scripted components? Or for statically compiled code that's separate for the engine? Or perhaps both ?
Both. We support the ability to dynamically add components as statically compiled C++ classes or as Lua scripts. They both inherit from behavior.
XianForce wrote:
Hmm, I never thought about using a template on that method... That's a great idea though :D.
But just to do a bit of prodding; So your Behavior class is just a base for scripted components? Or for statically compiled code that's separate for the engine? Or perhaps both ?
Both. We support the ability to dynamically add components as statically compiled C++ classes or as Lua scripts. They both inherit from behavior.
mmmm, juicy
God am I glad I picked now to get back to programming...
XianForce wrote:
Hmm, I never thought about using a template on that method... That's a great idea though :D.
But just to do a bit of prodding; So your Behavior class is just a base for scripted components? Or for statically compiled code that's separate for the engine? Or perhaps both ?
Both. We support the ability to dynamically add components as statically compiled C++ classes or as Lua scripts. They both inherit from behavior.
mmmm, juicy
God am I glad I picked now to get back to programming...
I've decided to rename this thread so that if anybody has issues with designing a game engine, they can come to this thread to ask questions. I'm going to ask the first question.
As you all know, I've been developing a game engine for the past few weeks and have been trying to implement a Component System. I'm almost done with my implementation, but unfortunately my code won't compile when I test out my game engine. I get the following error messages:
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_entity.h(12) : error C2011: 'SE::Entity' : 'class' type redefinition
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_entity.h(12) : see declaration of 'SE::Entity'
c:\programming\c++\splinter games\pickin' sticks\main.cpp(11) : error C2079: 'entity' uses undefined class 'SE::Entity'
c:\programming\c++\splinter games\pickin' sticks\main.cpp(13) : error C2228: left of '.addComponent' must have class/struct/union
type is 'int'
c:\programming\c++\splinter games\pickin' sticks\main.cpp(14) : error C2664: 'SE::System::addEntity' : cannot convert parameter 1 from 'int' to 'SE::Entity'
Source or target has incomplete type
c:\programming\c++\splinter games\pickin' sticks\main.cpp(16) : error C2228: left of '.getRenderComponent' must have class/struct/union
type is 'int'
c:\programming\c++\splinter games\pickin' sticks\main.cpp(16) : error C2228: left of '.text' must have class/struct/union
c:\programming\c++\splinter games\pickin' sticks\main.cpp(18) : error C2228: left of '.getRenderComponent' must have class/struct/union
type is 'int'
c:\programming\c++\splinter games\pickin' sticks\main.cpp(18) : error C2228: left of '.text' must have class/struct/union
c:\programming\c++\splinter games\pickin' sticks\main.cpp(20) : error C2228: left of '.getRenderComponent' must have class/struct/union
type is 'int'
c:\programming\c++\splinter games\pickin' sticks\main.cpp(20) : error C2228: left of '.text' must have class/struct/union
I'm guessing that the most important error is the first one.
I'm going to go ahead and guess that you have recursively defined "Entity" by including an include that includes entity.
You should be forward declaring any class that doesn't not require a header to be included. Unless you're declaring an instance of the object on the stack or are inheriting from the class, you shouldn't need the header.
I tried to forward declare the classes, but now my game engine doesn't compile. I have an Engine.h that includes System.h that includes Entity.h. When I try to forward declare both Entity in System.h and System in Engine.h, I get this error:
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_engine.cpp(22) : error C2027: use of undefined type 'SE::System'
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_engine.h(9) : see declaration of 'SE::System'
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_engine.cpp(22) : error C2227: left of '->update' must point to class/struct/union/generic type
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_rendersystem.cpp(7) : error C2027: use of undefined type 'SE::Entity'
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_system.h(8) : see declaration of 'SE::Entity'
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_rendersystem.cpp(7) : error C2227: left of '->getRenderComponent' must point to class/struct/union/generic type
I've tried just forward declaring one or the other, but I get the same errors.
lotios611 wrote:I tried to forward declare the classes, but now my game engine doesn't compile. I have an Engine.h that includes System.h that includes Entity.h. When I try to forward declare both Entity in System.h and System in Engine.h, I get this error:
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_engine.cpp(22) : error C2027: use of undefined type 'SE::System'
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_engine.h(9) : see declaration of 'SE::System'
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_engine.cpp(22) : error C2227: left of '->update' must point to class/struct/union/generic type
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_rendersystem.cpp(7) : error C2027: use of undefined type 'SE::Entity'
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_system.h(8) : see declaration of 'SE::Entity'
c:\programming\c++\splinter games\splinter sdk\splinterengine\source\se_rendersystem.cpp(7) : error C2227: left of '->getRenderComponent' must point to class/struct/union/generic type
I've tried just forward declaring one or the other, but I get the same errors.
You forward declare the class in the header file and actually include the header in the .cpp file.