Problems Encountered While Developing a Game Engine

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Re: Game Engine Troubles

Post by lotios611 »

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'
Here's some code:

main.cpp

Code: Select all

#include "SE_RenderComponent.h"
#include "SE_Entity.h"
#include "SE_Engine.h"
#include "SDL.h"

int main()
{
	SE::Engine engine;
	SE::RenderComponent *renderComponent;
	SE::Entity entity;
	entity.addComponent(renderComponent);
	entity.getComponent(renderComponent)->text = "This was a triumph";
	SDL_Delay(1000);
	entity.getComponent(renderComponent)->text = "I'm making a note here";
	SDL_Delay(1000);
	entity.getComponent(renderComponent)->text = "HUGE SUCCESS";
	SDL_Delay(2000);
	return engine.mainLoop();
}
SE_Entity.h

Code: Select all

#ifndef SE_ENITY_H
#define SE_ENTIY_H

#include <vector>
#include <algorithm>
#include "SE_Component.h"

namespace SE
{
	class Entity
	{
	public:
		void addComponent(SE::Component* component);
		SE::Component* getComponent(SE::Component* component);
	private:
		std::vector<SE::Component*> components;
	};
}

#endif
SE_Entity.cpp

Code: Select all

#include "SE_Entity.h"

void SE::Entity::addComponent(SE::Component* component)
{
	components.push_back(component);
}

SE::Component* SE::Entity::getComponent(SE::Component* component)
{
	for (int i = 0; i < (int)*components.end(); i++)
	{
		if (components.at(i) == component)
		{
			return component;
		}
	}
}
SE_Component.h

Code: Select all

#ifndef SE_COMPONENT_H
#define SE_COMPONENT_H

namespace SE
{
	class Component
	{
	public:
	};
}

#endif
SE_RenderComponent.h

Code: Select all

#ifndef SE_RENDER_COMPONENT_H
#define SE_RENDER_COMPONENT_H

#include "SE_Component.h"

namespace SE
{
	class RenderComponent : public Component
	{
	public:
		char *text;
	private:
	};
}

#endif
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
User avatar
thejahooli
Chaos Rift Junior
Chaos Rift Junior
Posts: 265
Joined: Fri Feb 20, 2009 7:45 pm
Location: London, England

Re: Game Engine Troubles

Post by thejahooli »

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

Code: Select all

((RenderComponent)entity.getComponent(renderComponent))->text = "This was a triumph";
However I do not personally think this is the best option, but I cannot think of an alternative off the top of my head.
I'll make your software hardware.
User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Re: Game Engine Troubles

Post by lotios611 »

That code works, but I also don't know if that's the best solution.
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
User avatar
MrDeathNote
ES Beta Backer
ES Beta Backer
Posts: 594
Joined: Sun Oct 11, 2009 9:57 am
Current Project: cocos2d-x project
Favorite Gaming Platforms: SNES, Sega Megadrive, XBox 360
Programming Language of Choice: C/++
Location: Belfast, Ireland
Contact:

Re: Game Engine Troubles

Post by MrDeathNote »

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.
http://www.youtube.com/user/MrDeathNote1988

Image
Image

"C makes it easy to shoot yourself in the foot. C++ makes it
harder, but when you do, it blows away your whole leg." - Bjarne Stroustrup
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Game Engine Troubles

Post by Falco Girgis »

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.
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Game Engine Troubles

Post by XianForce »

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 :o?
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Game Engine Troubles

Post by Falco Girgis »

XianForce wrote:
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 :o?
Both. We support the ability to dynamically add components as statically compiled C++ classes or as Lua scripts. They both inherit from behavior.
User avatar
eatcomics
ES Beta Backer
ES Beta Backer
Posts: 2528
Joined: Sat Mar 08, 2008 7:52 pm
Location: Illinois

Re: Game Engine Troubles

Post by eatcomics »

GyroVorbis wrote:
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 :o?
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...
Image
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Game Engine Troubles

Post by XianForce »

eatcomics wrote:
GyroVorbis wrote:
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 :o?
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...
Same thing is going through my mind right now :D
User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Re: Problems Encountered While Developing a Game Engine

Post by lotios611 »

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.

Here's my main.cpp:

Code: Select all

#include "SE_RenderSystem.h"
#include "SE_RenderComponent.h"
#include "SE_Entity.h"
#include "SE_Engine.h"
#include "SDL.h"

int main(int argc, char **argv)
{
	SE::Engine engine;
	SE::RenderSystem system;
	SE::Entity entity;
	SE::RenderComponent renderComponent;
	entity.addComponent(renderComponent);
	system.addEntity(entity);
	engine.addSystem(system);
	entity.getRenderComponent().text = "This was a triumph";
	SDL_Delay(1000);
	entity.getRenderComponent().text = "I'm making a note here";
	SDL_Delay(1000);
	entity.getRenderComponent().text = "HUGE SUCCESS";
	SDL_Delay(2000);
	return engine.mainLoop();
}
And here's my SE_Entity.h

Code: Select all

#ifndef SE_ENITY_H
#define SE_ENTIY_H

#include <map>
#include <string>
#include "SE_Component.h"
#include "SE_RenderComponent.h"

namespace SE
{
	class Entity
	{
	public:
		void addComponent(std::string componentType, SE::Component component);
		SE::Component getComponent(std::string componentType);
		void addRenderComponent(SE::RenderComponent renderComponent);
		SE::RenderComponent getRenderComponent();
	private:
		std::map<std::string, SE::Component> components;
		SE::RenderComponent _renderComponent;
	};
}

#endif
If I haven't provided enough code, please tell me.
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Problems Encountered While Developing a Game Engine

Post by Falco Girgis »

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.
User avatar
lotios611
Chaos Rift Regular
Chaos Rift Regular
Posts: 160
Joined: Sun Jun 14, 2009 12:05 pm
Current Project: Game engine for the PC, PSP, and maybe more.
Favorite Gaming Platforms: Gameboy Micro
Programming Language of Choice: C++

Re: Problems Encountered While Developing a Game Engine

Post by lotios611 »

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.
"Why geeks like computers: unzip, strip, touch, finger, grep, mount, fsck, more, yes, fsck, fsck, fsck, umount, sleep." - Unknown
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Problems Encountered While Developing a Game Engine

Post by Falco Girgis »

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.
Post Reply