What is your opinion and how would you do a structure that has multyple functionalities

Started by
10 comments, last by Servant of the Lord 9 years, 11 months ago


But the reason i don't load from external file the structures is because they are dynamic, i don' know a farm is farm.
To know if X posses a farm i check if he has Land(Grow crops, trees...) or livestock and a building(with tools inside for cultivating land, livestock inside...).
There fore i decide what a building is depending on what is inside on fly.

OK, I understand. You really should look at component based systems. That's what you have here.

Instead of manually checking

if (Entity.Has(SomeComponent)) DoThis()

you should have it done manually, meaning, you have a system that is automatically executed when an entity has specific components.

Good luck.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Advertisement

Here is a compilable C++ example using bitflags:


#include <iostream>
using namespace std;

namespace SF
{
	enum Enums {None, CanStore = 1, CanRest = 2, CanTrain = 4, OnWater = 8, OnLand = 16, CanProduce = 32, CanOperate = 64, OnWaterAndLand = OnWater|OnLand};
}

typedef unsigned int StructFlags;

int main()
{
	StructFlags structureFlags = SF::None;
	
	structureFlags |= SF::CanStore;
	
	structureFlags |= (SF::CanOperate | SF::CanProduce);
	
	structureFlags |= SF::OnWaterAndLand;
	
	if(structureFlags & SF::CanStore)
		std::cout << "This building can store stuff." << std::endl;
		
	if(structureFlags & SF::CanOperate)
		std::cout << "This building requires people to operate it." << std::endl;
	
	//  |--- Notice the '!' to negate the result.
	//  v
	if( !(structureFlags & SF::CanTrain))
		std::cout << "This building can NOT train people." << std::endl;
	
	if(structureFlags & SF::OnWaterAndLand)
	{
		std::cout << "This building is on both water and land." << std::endl;
	}
	else if(structureFlags & SF::OnWater)
	{
		std::cout << "This building is only on water." << std::endl;
	}
	else if(structureFlags & SF::OnLand)
	{
		std::cout << "This building is only on land." << std::endl;
	}
	else
	{
		std::cout << "This building is not on water or land." << std::endl;
	}
	
	return 0;
}

[Execute it and play around with it] - ideone.com


I wouldn't use component-based design for this situation. Just because objects have components, that doesn't mean they need to be built out of components.
Component-based design (also called ECS - entity component systems) is useful for many games, but in this situation he's asking for flags to branch his logic. Most ECS architectures are designed for graphics components, physic components, logic components, and so on. What's he's doing is dozens of Logic component, Logic component, Logic component, Logic component. That makes it closer to a finite-state machine that a component-based architecture. wink.png

It's not the correct fit in my opinion, and if he looked into component based design, it'd lead him on a wild goose chase to implement or learn how to use something that solves a problem he's not currently having. mellow.png

Example: ALL his structures will have appearances. ALL his structures will have locations on the map. There's no need for components in this situation. It's not different pieces of the engine being composed together. Just because it's composable at runtime doesn't mean we need to make it into components.


ECS architectures are really cool and I'm really excited about them. tongue.png I personally feel that they'll stick around as one of our most-used architectures, at least where games are concerned - but they shouldn't be applied everywhere.

In this case, I think the OP was actually correct that this best fits the idea of flags. Whether those flags are implemented using bools, std::set<std::string>, std::bitsets, bitflag enums, or any of another implementation, it doesn't particularly matter.

If we take the OP's structure:


        SFStorage = 0x01,//Used to drop resources
        SFRest = 0x02,//Used to sleep at night
        SFTownHall = 0x04,//Used to get actions from
        SFBarrack = 0x08,//Used for training/ getting battle/scout/guard actions for day
        SFOnWater = 0x10,//This structure is on water
        SFOnLand = 0x20,//This structure is on land
        SFOperationable = 0x40,//Uses people to operate, instead of automatic
        SFProduces = 0x80,//Produces resources


What we actually see is that the flags are all logic-based, and fit into several categories:

[where they can be located] (SFOnLand, SFOnWater)

[what they can do] (SFStorage, SFRest, SFBarrack, SFTownhall(?))

[whether they produce or not] (SFProduces)

[what they require] (SFOperationable)

I feel the simplest way to describe the structures would be to design the class around those categories:


//If using C++11, this should be an 'enum class'
namespace GroundType
{
	//Since there are only three states, I wouldn't use bitflags here.
	enum Enum {Water, Land, WaterAndLand};
}

//Even if using C++11, this *shouldn't* be an 'enum class'.
namespace Action
{
	//I'm using bitflags here, plain ol' bools would also work just fine.
	enum Enum {None, CanStore, CanRest, CanTrain, CanShelterInside};
};
typedef unsigned int Actions;

struct Stats
{
	int currentHealth;
	int maxHealth;
	
	int defense;
	int rangedDefense;
};

struct Production
{
	int actionPoints; //For town-halls, for example.
	int iron;
	int copper;
	int food;
	int wood;
	//...etc...
};

struct Structure
{
	std::string name; //For example, "Town hall".
	std::string description; //"The place where villagers come to hang out after a hard day's work."
	
	Stats stats;
	GroundType groundType; //The type of ground the structure can exist on.
	
	//Per turn, or per minute, or whatever. Non-producing structures just produce '0'. No flag needed.
	Production production;
	
	//No flags needed for operation.
	int numPeopleOperating;
	int minPeopleRequiredToOperate;
	
	//The actions the player can use this building for.
	Actions actions;
};

This topic is closed to new replies.

Advertisement