6
\$\begingroup\$

So I'm making a small game where I generate 2D landscape using perlin noise when the game first loads.

I've got it working in a OO way, but want to move over to an ES architecure, and I'm just struggling to work out the right place for the code that does the generation to go?

In OO world, I have a World object which gets passes a coordinate value that is used as the seed for the perlin noise, and generates all the points for the land mass when the world is created.

I'm thinking I need a World component with a coordinate field on it - that's an easy part.

From there - is it right for a component to generate data when it's first initialised (or is that too OO?)? Or should a System be doing that instead, when the game first starts?

Or... some other solution I'm not aware of?

Thanks in advance for any guidance.

\$\endgroup\$
  • 6
    \$\begingroup\$ Remember that an EC system is not trying to get rid of OO. It's more focused on getting rid of inheritance problems. Also you can use whatever you want that works (even inheritance). There's no strict rules to follow. \$\endgroup\$ – MichaelHouse Dec 18 '12 at 3:26
5
\$\begingroup\$

I come from the mindset that components contain nothing more than data. Depending on your game, that data is derived from static files that ship with the game to sometimes being combined with the information sent from the game world server to your client if we're talking about networked games.

That implies that rather than components generating anything, I prefer to offload that to systems. I prefer this route because it sometimes makes sense for a component to be shared across a few systems and rather than trying to muck with managing all that logic in one class with an Update() method, I can separate it out into multiple systems and allow each system to work with that same component.

As an example, when your game loads, you have some level data file that desribes what you want this level to look like, what entities exist within it, where, what their attributes consist of, etc. So this LevelLoader reads this level file and determines it needs to place an Orc in the scene at 1, 10, 5.

// Allocate an Entity Id (in our case its just an unsigned int)
TEntityId id = mEntitySystem.CreateEntity("Orc123");

// Create position
PositionComponent& position = mEntitySystem.AddComponent(id, "Position");
position.SetPosition(1, 10, 5);

// Create renderable
RenderableComponent& renderable = mEntitySystem.AddComponent(id, "Renderable");
renderable.SetMesh("UglyOrc.mesh");

// Allows components to wire up references, etc for given id before it
// gets added to the world.
mEntitySystem.Finalize(id);

// Add entity to the world, will start to receive world messages
mWorld.AddEntity(id);

To relate the above to your example, I'd probably abstract the creation of the terrain to some type of terrain generation system. Once the landmass has been created by the terrain system, you could easily adjust the above code as follows:

// Create position
PositionComponent& position = mEntitySystem.AddComponent(id, "Position");
position.SetPosition(mTerrainSystem.GetGroundPointAt(1, 10, 5));

The Terrain System would look at the generated heightmap, determine what the right height should be at that point to place the Orc on the ground, return the proper adjusted position and that would cause the entity to appear above ground but relative to the same two directions in 3D space.

HTH.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the input! So when your game loads up all your entities (from file, or from code, doesn't matter), at that point you would tell you Terrain System to generate the terrain at that point? If so, this seems pretty reasonable to me. \$\endgroup\$ – Mark Mandel Dec 18 '12 at 22:42
  • \$\begingroup\$ @Mark Since Terrain is dynamic for your in this case, you could easily generate the terrain first and then by using the API I showed above, you query to get the Y height and simply adjust your entity's position position's starting transform when you load the level data. This seems more logical in flow of processing a level load to me. \$\endgroup\$ – Naros Jan 14 '13 at 22:54
  • \$\begingroup\$ @Nik-Lz In a very generic way, yes. My goal was to abstract away the component system registration & array management behind the entity manager so that the code which builds entities remained clean and did not need to know anything about the systems themselves. I have since reworked the loader where I dispatch the model data to a series of callbacks that systems register at startup. This allows each system to build the components without the loader needing to know about them either. It then boils down to a "link/sync" step and then runtime queries during the game loop. \$\endgroup\$ – Naros Oct 1 '18 at 14:33
4
\$\begingroup\$

Just because you want to use an entity-component architecture doesn't mean you need to use it for every game object. Forget about trying to implement edge cases like terrain as a collection of generic components, because all you'll end up with is components specific to terrain.

Entities are really only good for game objects that exist in many different forms with differing behaviours depending on the values of certain properties, like mobs. Instead of making terrain an entity, make it an intrinsic part of the physics/collision systems. That way, your entities can raycast and pathfind and bounce around and interact with the terrain without needing to handle the terrain differently than the other static objects in the scene. Hell, the entities don't even need to know that the terrain exists, just that they can interact with it if it does.

\$\endgroup\$
  • \$\begingroup\$ True. I believe the player entity would benefit out of this the most. The player shouldn't be just another generic entity, since it will probably have many of the available components in the game (ie cross a lot of domains) it can instead be a class that holds all its components/data together and on update() it iterates over them all. \$\endgroup\$ – Nikos Oct 6 at 23:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.