🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

How do i solve this elegantly?

Started by
2 comments, last by LorenzoGatti 4 years ago

Hi everybody,

I am currently working on a turnbased strategy game like civilization. I am creating the game in C# using Visual Studio.

In the game i have defined several classes. Two of the relevant classes are Units and Buildings. A Unit can have different types, for example Archer, Spearman, etc. The same goes for a Building.

I have defined two Enums (BuildingType & UnitType). Each Unit or Building will have either UnitType or a BuildingType.

Of course, Buildings & Units behave differently. However, they can both be produced by a city. Besides these objects a city can also produce basic resources such as food or gold (these resources are also stored in an enum ResourceType).

Within a city I want to to present the player with a list of all stuff they can build, meaning all unittypes, buildingtypes and resourcetypes. For each item in the list i want to display an image, the amount of turns it takes to produce it, etc.

How do i do this elegantly? Should i work here with inheritance (i personally don't think so), with an interface (that sounds already a bit better) and if so, in what way? Or is may basis completely wrong and would i have to code this differently?

Thank you in advance!

PS. My game is called Civilization Wars, check it's first version out here!

https://gamejolt.com/dashboard/games/127941

My personal blog on game development!

Black Wolf Game Development

Advertisement

You can of course solve this in different approaches where one is inheritance by a base class, another one is your interface approach (which is inheritance btw. too) and you could also work in an ECS like environment. It is up to you what fits best.

I would use the ECS approach and simply add an Entity to the list for everything you want to display, that have components for all the data (an Icon-Component and Building-Component) but you also can use the interface approach if you don't want to inherit everything from a common base class.

Usually you have a kind of database that creates those objects for you rather than defining them in code. It has the advantage to not change the code every time you want to add/remove or change an existing building/unit/resource/whatever.

Finally it depends what environment you are using/ which and if you are using a game engine. Unity has ECS built-in but as you wrote you work in VisualStudio, I assume you are using plain C# and so have access to the DLR and Reflection. So I describe too approaches I use in my code that are based on the ECS model, because of two reasons:

  • You don't need to define data instances in every class rather than maintain it's components and reduce initialization complexity
  • You can handle instances differently depending on their components

If you want to run a simple ECS approach for example, you need to identify your classes as entities. I do this by an interface (IEntity) that my classes inherit and provide an EntityId, that is set by the class. Then I maintain dictionaries for each ComponentType and simply perform a lookup if a ComponentId exists that matches my Entity. Put all this together into some extension methods so I have AddComponent, GetComponent and RemoveComponent on any class that inherits from IEntity. As entities are defined as a single ID, you can also reference to an existing entity by a component without knowing the entity itself.

The other approach I tried (successfully) is utilizing the capabilities of the DLR (dynamic language runtime) which are used in dynamic objects. This is a wrapper around some CLR related type definition code allowing to dynamically set and get properties of an object at runtime without defining those properties in beforehand. An example:

class CourtHouse
{
    public int AmountOfRooms { get; private set; }
    
    public CourtHouse(int amountOfRooms)
    {
        this.AmountOfRooms = amountOfRooms;
    }
}

dynamic myLargeCourtHouse = new CourtHouse(15);
myLargeCourtHouse.Icon = new Bitmap("<asset path>");
myLargeCourtHouse.ConstructionTime = 50;
myLargeCourtHouse.Cost = new ResourceIdentifier(ResourceType.Money, 10000);

What this code does is initializing an instance of a simple class in C# and utilizing the DLR to add dynamic properties to the class which can be of any type and any name.

Making use of this for an ECS can be as simple as try/catch test for properties or you can override DynamicMetaObject and provide your own Binder instance that feeds your ECS system in the background. Take care as this is a lot of try/error until it fully works but you can achieve a level of dynamic objects that are far beyond those the runtime offers by default.

In our SDKs Compound Package we are doing exactly this to be able to add dynamic properties to our objects, dynamic functions and even dynamic inheritance of interfaces !at runtime!. The package is not meant to be an ECS but help us write classes to be used in our Editor code to primary fit into necessary interface definitions. But it can be even used in an ECS environment as everything can be tested for and we have Try-methods for it

Jaap85 said:
Within a city I want to to present the player with a list of all stuff they can build, meaning all unittypes, buildingtypes and resourcetypes. For each item in the list i want to display an image, the amount of turns it takes to produce it, etc.

This isn't in the same hierarchy as the types of buildings and units: it is a list of public priorities or maybe tasks for citizens, some linked to new or existing buildings and units, some linked to resource types, and some “special” (e.g. idle malcontents, maintenance or drills, commerce, festivals and leisure time to improve population happiness…).

The most obvious concrete design is a Task class, with very specialized subclasses like “twiddle thumbs” and more generic ones such as “build any unit”, “build any building” and “harvest any resource”, or an adaptation to an ECS with a shallower hierarchy (constructing units, constructing buildings and harvesting resources, along with other task effects, could become components in task entities).

It's also important to distinguish abstract potential tasks (e.g. recruit 1 infantry) from their executions (e.g. one infantry will appear on turn 22 in barracks 3, another on turn 26 in barracks 4) that can be suspended, altered, paid for separately, etc.

Omae Wa Mou Shindeiru

This topic is closed to new replies.

Advertisement