Could interfaces representing each attribute of a player class be appropriate? Are there problems with this?
As attributes are added to the model, so will interfaces resulting in a long declaration.
public class Player : INamed, IEnergy, IInventory, IMana, ...
{
public string Name { get; set; }
public int Energy { get; set; }
public int Mana { get; set; }
public Inventory Backpack { get; }
...
}
To me, that would tell me that not all players have a name, energy, etc. For a basic game, all units usually have some sort of name and a series of hit points which denote how much damage can the unit take.
If all the units in your game have similar properties but different values (maybe a priest can withstand less damage than a soldier, but can move faster since it does not have armor), you could define an interface which specifies the behavior of your units, thus you could have something like so:
public interface IBaseUnit
{
int HitPoints
..
}
Then, each specific unit will have their own implementation. That being said, I would presume that the units will act in a similar fashion in most things, thus, it might be more effective to use an abstract class instead of an interface at the top of your hierarchy.
In my opinion, what you need is a class hierarchy, not a bunch of interfaces. Instead of building a large pool of "properties" that different characters can have, you'd be more well advised to model some sort of hierarchy with some base abstract classes that concrete units inherit from.
A basic idea:
abstract class Character
{
String name
int hitpoints;
IList<Item> inventory;
}
abstract class Spellcaster : Character
{
int manapoints;
IList<Spell> knownSpells;
}
class Mage : Spellcaster
{
// Mage specific stuff
}
class Necromancer : Spellcaster
{
// Necromancer specific stuff
}
And so on. Obviously the classes that you model will depend on what kind of game it is that you are making.
Related
Basically I'm trying to create a attatchment system for a 2D platform/shooter game, the weapon system is working great but I want to implement some attachments, diferent barrels, magazines even ammo types.
For the simpler ones that just modify a stat I was thinking of just creating a class or even a struct with all the possible stats (damage, recoil, spread etc) and just setting them to the appropiate values (+1, -5, 0 if it doesn't use it). However, there are some ideas that might require a separate method/function, like shooting different bullets.
My main question is would it be more effective/efficient to just make smaller scripts for the edge cases and a main one for the simple stat changers. Or should I just overload a main script/class with methods for all the possible attachments?
There aren't that many "special" attachments, but i'd like to make a system that expandable if possible.
Im not an expert programmer (I just learned about enums a couple days ago!) so any suggestions are greatly appreciated.
I would use Unity's ScriptableObject class to create an abstract class then inherit from that abstract class to create more spesific classes and abstract classes.
Then I would create my attachments etc. in unity editor and modify whatever value I want from it.
An example armor piece would inherit the following ArmorItem class and use the ApplyEffect method to make the player bigger to show that you can make any type of modification.
ItemBase class
using UnityEngine;
public abstract class ItemBase: ScriptableObject
{
public string ItemName;
public abstract void ApplyEffect();//override this method for any edge case items
}
ArmorItem
public abstract class ArmorItem: ItemBase
{
public float Armor;//use this however you want
}
EdgeCaseArmor
[CreateAssetMenu(menuName = "Items/Armor/EdgeCaseArmor")]
public class EdgeCaseArmor: ArmorItem
{
public override void ApplyEffect()
{
//find player and make it bigger
GameObject.FindGameObjectWithTag("Player").transform.localScale *= 1.5f;
}
}
Obviously you will need to load items and somehow call ApplyEffect. You can do it at the start of the game by adding this to a start method.
var item = Resources.Load("path to your scriptable object that inherits ItemBase") as ItemBase;
item.Activate();
How you load the items and call them is up to you. You will need to save your scriptable objects in Assets>Resources folder(create one if you haven't created one already).
You can also make multiple armors with different names, armor values etc. like this.
Note that if you want to have an armor with no special effect you will need to make ArmorItem a normal class or make a NormalArmor class that inherits ArmorItem. Just leave the ApplyEffect function empty if you don't want any special effects.
This is a fairly general question so keep in mind that you may get several varying opinion-related answers.
With that said, the biggest suggestion that I would give is to look into Inheritance. Using a series of interfaces and classes to more refine the base concept of "item modifications".
For instance, I would create an interface:
interface IItemModification
{
void Apply();
}
Any more refined modification class or interface would implement (in the case of a class) or inherit (in the case of another interface) this interface.
In this example we will just create a base class that implements that interface:
public class ItemModification : IItemModification
{
public void Apply()
{
// Logic to apply modifications to the item.
}
}
In the case above, you now have a very basic class that represents an item modification which contains the implementation of the interface.
Next you might want to go into further detail, perhaps by creating item type implementations:
public class WeaponItemModification : ItemModification
{
public ArmorItemModification(StatModifiers modifiers, AttackType attackType)
{
this.Modifiers = modifiers;
this.Attack= attackType;
}
public AttackType Attack
{
get; set;
}
public StatModification Modifiers { get; set; }
}
public class ArmorItemModification : ItemModification
{
public ArmorItemModification(StatModifiers modifiers, DefenseType defenseType)
{
this.Modifiers = modifiers;
this.Defense = defenseType;
}
public DefenseType Defense
{
get; set;
}
public StatModification Modifiers { get; set; }
}
Of course a logical progression of that would be more specific item types:
public class VestModification : ArmorItemModification
{
public VestModification(StatModification modifiers, DefenseType defenseType, AreaProtectionType areaProtectionType)
{
this.Modifiers = modifiers;
this.Defense = defenseType;
this.AreaProtection = areaProtectionType;
}
public AreaProtectionType AreaProtection
{
get; set;
}
}
These are just some basic examples to point you in the right direction. I would suggest reading up on inheritance concepts to get a better understanding of it.
i was looking at facade-like delegation in classes, for example let's suppose that you got the Equipment class ( with Equip() and UnEquip() methods), and then you have a Player class which has a reference to the Equipment.
The way i would implement the Player class is to have some public methods like EquipItem and UnEquipItem, and those methods will delegate the tasks to the Equipment class. Now if the player also has another class that does stuff, like movement, then i would put again some public methods on the Player class that delegates to the Movement class, in a facade-like way. Now one of the disadvantages of the facade pattern is the growing interface the more classes or systems it handles. And let's suppose that i know that in the future, the Player class will have alot more functionality.
I don't know if this is the correct approach, nonetheless i was thinking if it would be possible to expose the Equipment and Movement references as properties, like so:
Class Player
{
public Equipment equipment { get; set; }
public Movement movement { get; set; }
}
Now, i know that exposing the object's state is bad, but this way you have a better control of the growing interface of the class, and have more focused methods on the Player class. So instead of:
player.Equip();
you can do
player.equipment.Equip();
Sooo finally, my question would be what is the best approach in this scenario, or maybe i got something wrong ?. Thanks
PS: the example is from a game area, but the solution doesn't have to be necessarily applicable to games, i just thought it was simple to understand.
An alternate approach would be to develop a set of command actions that can be applied to the player which manipulate the state. While the command objects would have extended access to the player, the outer API would keep the implementation details as a black box.
As an example:
public abstract class Action
{
public abstract void ActOn(Player player);
}
public class EquipAction : Action
{
private Item item;
public EquipCommand(Item item) {
this.item = item;
}
public void ActOn(Player player) {
player.Equipment.Add(item);
}
}
public interface IPlayer
{
void PerformAction(Action action);
}
public class EquipmentSet
{
public List<Item> Items { get; private set;}
}
public class EquipmentManager
{
public Add(Item item) {
}
public List<Item> Items { get; }
}
public class Player : IPlayer
{
public EquipmentManager manager;
public PerformAction(Action action) {
action.ActOn(this);
}
public List<Items> Equipment {
return manager.Items;
}
}
Now obviously, there's a lot more that should be done to make this fully capable to do what you want, but the idea would be to limit your public interface to player to the structure that you want to expose (e.g. attributes, equipment, status, .etc) and delegate all the verbs to actions.
Under the covers, the actual functionality of a Player could be broken up into as many components as would make sense to limit the size of each individual components.
I need a system of classes that describes a planetary system.
My first class is an atomary space body:
public class SpaceBody
{
public string Name;
public float Mass;
// and so on
}
The second one is a system of space bodies and it also is SpaceBody:
public class SpaceBodySystem<ChildType>: SpaceBody where ChildType: SpaceBody, new()
{
// ...
public List<ChildType> Children;
// ...
}
Next, I have a star:
public class Star: SpaceBodySystem<SpaceBody>
{
public float Intencity;
// ...
}
And finally, the whole star system is something like this
(it can have more than one star):
public class StarSystem: SpaceBodySystem<Star>
{
public bool OccupiedByAliens;
// ...
}
The problem is:
The stars should have planets (SpaceBodySystem) which in turn, may have their satellites and those satellites also may have their own satellites and so on... nesting depth is unlimited.
It's impossible with my current class system.
I have to write something like this but this ugly solution has limited hierarchy level.
public class StarSystem: SpaceBodySystem<SpaceBodySystem<SpaceBodySystem<SpaceBody>>>
{
public float Intencity;
// ...
}
I ask the community to give me some advises how this structure can be improved.
I thought about other scheme (interfaces, composition + delegation) and didn't managed to get an acceptable solution.
Many thanks for any help.
If you need the possibility to have multiple suns in a system, maybe you also want the possibility of two planets sharing a moon.
In that case, maybe you should have a SubSystem, which has an array of main bodies and an array of satellites. In a solar system, you can use stars as the main bodies and the planets as satellites. In a galaxy, maybe you can define some abstract centerpoint/waypoint as the main body and all the solar systems are satellites.
So for our solar system, you've got the SubSystem 'SolarSystem', with main body Sun and sattelites planets, each of which are subsystems as well. Subsystem Earth has a main body Earth and a satelite Moon.
Having a SubSystem Earth with one MainBody Earth might sound a bit redundant, but maybe you can solve that by using interfaces, so a simple subsystem like that (with one main body) can be implemented by a single class that implements both ISubSystem and IMainBody.
Or you can keep the implementation easier and make Earth(system) a separate subsystem with an array with one main body, which is Earth(planet) and an array with one satelite, which is the SubSystem Moon(system), containing main body Moon and no satellites.
I think one class will do to set up a planetary system:
public class SpaceBody
{
public string Name;
public float Mass;
public float Distance;
public bool clockwise;
//...
public SpaceBody RevolvesAround;
List<SpaceBody> Satellites;
}
If your base class for systems can have children which are themselves instances of, or derived from, that same base class, then you don't need to nest like that. Let me give an example:
public class SpaceBodySystem<ChildType>: SpaceBody where ChildType: SpaceBody, new()
{
public List<ChildType> Children;
}
So, a SpaceBodySystem has children that are SpaceBody types, and it is itself a SpaceBody.
public class StarSystem : SpaceBodySystem<Star>
{
}
This class can represent a star, or a binary pair of two stars, or whatever.
public class PlanetarySystem : SpaceBodySystem<Moon>
{
public Planet CentralPlanet;
}
This can represent a planet with any number of moons, where Planet inherits from SpaceBody.
public class SolarSystem : SpaceBodySystem<PlanetarySystem>
{
public StarSystem CoreStar;
}
This class can now represent a solar system with some configuration of stars, and children which are all planets which may have moons.
In short, you don't need to keep nesting SpaceBodySystem<SpaceBodySystem<SpaceBodySystem<SpaceBody>>> because SpaceBodySystem inherits from SpaceBody, so if you just have SpaceBodySystem<SpaceBody>, then that inner SpaceBody might be a SpaceBodySystem, which might have further children, but you don't need to know that. That's the beauty of polymorphism.
Need to say in addition, I want to load my system from data file.
Suppose, I have this input data (in attachment).
And I have virtual method that reads and creates an object of SapceBody.
class SpaceBody...
{
...
public virtual void CreateGameObject()
{
instance = new GameObject();
}
...
}
class SpaceBodySystem...
{
...
public override void CreateGameObject()
{
base.GameObject();
foreach(ChildType child in Children)
{
child.CreateGameObject();
}
}
...
}
class Star: SpaceBodySytem<SpaceBody>
{
...
public override void CreateGameObject()
{
base.GameObject();
doExtraWorkForTheStar();
}
...
}
StarSystem.CreateObject();
// for attached file, will load and create one star (Sun) and nine planets.
So, if I use the declaration proposed by anaximander, the system doesn't see children of children.
For example, the Earth is SpaceBody (but should be SpaceBodySytem) and will not create Moon in this case.
The GolezTrol's idea is fine.
solarsystem.json
let's say that I want to collect in one place all common properties and behaviors for all sports. I was thinking to use SportBase as abstract class for this purpose but I'm not sure. I'm trying to understand the differences between Abstract vs Interface usage on this example.
Every sport should have following properties
DateTime Started;
DateTime Ended;
string Name;
What if I declare these properties like integers and later on I decide to use Game object as separated entity like Game StartGame. I do not see clearly which approach to use with high level of abstraction to reduce pain on later modification (this modification can have adding new properties, new behaviors, etc.)
Thanks
if you only have properties and empty methods an interface might be your better choice. if you have some actual code then abstract class is your only option. also remember that you can inherit only one abstract class but implement multiple interfaces.
You can use an interface to provide a contract to code to.
public interface ISportsEvent
{
DateTime Start { get; set; }
DateTime End { get; set; }
string Name { get; set; }
}
but that doesn't give you a reusable implementation
As a general rule you should prefer composition over inheritance.
So its often better to do something like this
public interface EventDetails
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public string Name { get; set; }
}
public class SportingEvent
{
public EventDetails Details {get;set;}
}
now this is a bit rough but you can see what I'm getting at.
No, I wouldn't do that. You'll end up creating an abstract God class, which has way to many responsabilities.
I personally would probably make it an abstract class, since not only will your sports share some fields, but they might share some logic too.
Interfaces aren't for seperating out duplicate code, but they're purely for polymorphism.
All an interface does is guarantee that your class will act a certain way. If you plan on putting logic in your base class than you want an abstract class.
I'm looking to learn how to use interfaces and base classes effectively. I'm not exactly sure where to put common properties? Do only behaviors belong in an interface? If properties such as: Color and MinSpeed shouldn't go in the interface, where should they live? In an abstract class?
public interface IVehicle
{
void Speed();
void Clean();
void Stop();
}
public class Bmw : IVehicle
{
// Because these pertain to every vehicle no matter of maker,
// should these propertes go in the interface? Or in an abstract class?
public string Color { get; set; }
public int MinSpeed { get; set; }
#region IVehicle Members
public void Speed()
{
}
public void Clean()
{
}
public void Stop()
{
}
#endregion
}
Interfaces can be thought of as a contract that must be satisfied by any implementing class. Use it if you want to guarentee that all classes do the same thing—satisfy the same API—but you don't care how they do it. If properties are a part of that API, then by all means include them in your interface.
From your example above, if you want all cars to be guaranteed to have a color and minSpeed, then those properties belong in the interface. If those properties are specific to BMWs alone, then they belong in the BMW class. If those properties belong to some classes but not others, you could create a new interface extending the original one:
public interface IVehicleWithColorAndMinSpeed : IVehicle
{
string Color { get; set; }
int MinSpeed { get; set; }
}
(just don't get carried away with this)
Abstract classes are similar, but allow you to provide a default implementation for your sub classes.
Abstract classes tend to be easier to version, since you can add something new to your API, and provide a default implementation that your existing subclasses will automatically pick up; adding something to an interface immediately breaks all existing classes which implement that interface.
The 'right' answer is entirely dependent on your domain model. What is the problem you're trying to solve? There is no 'right' answer other than the one which solves the particular problem at hand with the greatest:
understandability
maintainability
brevity
isolation
performance
You can probably consider most of those properties to be in order of importance, but they mean different things to different people and there's probably a lot of debate implied there too.
Can you tell us any more about the particular application you imagine these classes to serve?