Using Generics to Access Classes in an XNA Game - c#

If I have a class that is based off another class, how do I access the properties of the first class if it can have any name? I was thinking of using generics to access the properties, but the generics are "generic" for a reason...
For example:
public class AGameInXNA : Microsoft.Xna.Framework.Game
{
int ExampleGameProperty;
}
// ... another class ... //
public class ReferenceToAGameInXNA
{
Game gameInstance;
public void SetGameInstance(Game game)
{
gameInstance = game;
}
public void SetExampleGameProperty()
{
gameInstance.ExampleGameProperty = 21; // I don't know the name of
// AGameInXNA, so I want to
// access it using a generic
// class.
}
}
I know that that does not work, so how would I use generics in this case to access the AGameInXNA's properties in another class if I don't know AGameInXNA's name?
EDIT: I am trying to make it so that I can reuse this code later on. I want to be able to have a class that is unknown, such as public class unknownclassname that extends another class, such as Microsoft.Xna.Framework.Game, and be able to access the class unknownclassname without directly calling/implementing it in the library code.

I would recommend looking into XNA Services.
So for example, you would create a service which could be as simple as an
interface IExamplePropertyService
{
int ExampleProperty { get; set; }
}
public class AGameInXNA : Microsoft.Xna.Framework.Game, IExamplePropertyService
{
int ExampleGameProperty { get; set; }
void Initialize()
{
// Do other initialization
Services.Add( typeof(IExamplePropertyService), this );
}
}
public class ReferenceToAGameInXNA
{
IExamplePropertyService propertyService;
public void GetGameInstance(Game game)
{
propertyService = (IExamplePropertyService)game.GetService( typeof(IExamplePropertyService) );
}
public void SetExampleGameProperty()
{
propertyService.ExampleGameProperty = 21;
}
}
Implement it, and register it with the Game component, then in your ReferenceToAGameInXNA, you would query for this service and store it (rather than the Game) for use later.
As a bonus benefit, The IExamplePropertyService no longer even needs to be implemented by the Game class, it could be implemented by any GameComponent.
This makes for an easy way to seperate classes from having to know about the inner workings of other classes in the Game. So long as the services exist somewhere, your ReferenceToAGameInXNA can be used.

I don't think generics are what you are actually looking for here. In your second class, just change the type of all of the gameInstance to the type of the class you created for your game, in this case AGameInXNA. There should only be a need for one subclass of the Game type in each XNA game. That will allow you to access any public members of AGameInXNA from the Reference class.
If this isn't what you are after, please give a more detailed explanation of what you are trying to accomplish and I'll try to help you.

I don't know XNA, but if you want to have several classes that inherit from Game and have the same property on all of them, you could create an abstract class that inherits from Game and let the other classes inherit from that instead.
(Also, your GetGameInstance() is badly named, because it sets the field, it doesn't get it. And it's probably better as property anyway.)
public abstract class GameBase : Microsoft.Xna.Framework.Game
{
public int ExampleGameProperty { get; set; }
}
public class AGameInXNA : GameBase
{
// code specific to AGameInXNA
}
public class ReferenceToAGameInXNA
{
public GameBase GameInstance { get; set; }
public void SetExampleGameProperty()
{
GameInstance.ExampleGameProperty = 21;
}
}
If the other classed that have ExampleGameProperty shouldn't inherit from Game, you could create an interface instead. AGameInXNA would then inherit from Game directly and it would also implement the interface. And you would work with that interface in ReferenceToAGameInXNA.

using "Game gameInstance;" you can not acess ExmpleProp. You should use "AGameInXNA gameInstance;" too access ExampleProp.

Related

how to change a get component class base on string?

So im trying to use compToGet string that have been passed through the parameter into slot.GetComponent().level++;
upgradeFoundation() will be called on button click.
and there is actually quite a lot of buttons with similar functionality (like: upgradeTurret(), upgradeTurret2(), etc)
thats why im trying to change the value of compToget string base on which button you click and use that new string to get component under the name of that new string but it seems it doesn't work that way and I dont know how it would work any other way, any help would be much appreciate.
public void upgradeFoundation()
{
float upgFoundationCost = slotGroup.transform.Find(slotName).gameObject.GetComponent<Slot>().upgFoundationCost;
Upgrade(upgFoundationCost, "Foundation");
}
public void Upgrade(float upgCost, string compToGet)
{
GameObject slot = slotGroup.transform.Find(slotName).gameObject;
if (inGameUIManagerScript.money >= upgCost)
{
Type compToGetType = Type.GetType(compToGet); //im not sure how to convert a string into a type
slot.GetComponent<compToGetType>().level++; //this is the error line saying im treating a var like a type
}
}
Thank you in advance.
Exactly the same issue as in your previous question => You can not use the generic! Instead use GetComponent(compToGetType);
However I removed the duplicate since you still would need to cast to your actual type which is anything but trivial!
=> Again I can only recommend: Don't use strings!
Rather have a common Base class or interface like e.g.
public abstract class BaseComponent : MonoBehaviour
{
private int level;
// public read-only access
public int Level => level;
public virtual void Upgrade()
{
level++;
}
// Other properties and methods all your components have in common
// Also get into "virtual" and "abstract" members!
}
and inherit your stuff from it like
public class Foundation : BaseComponent
{
// Additional stuff specific to the foundation
// overrides for the virtual and abstract members
}
public class Turret : BaseComponent
{
// Additional stuff specific to the turret
// overrides for the virtual and abstract members
}
//Maybe this would even inherit from Turret instead?
public class Turret2 : BaseComponent
{
// Additional stuff specific to the turret2
// overrides for the virtual and abstract members
}
and finally use that common base instead:
public void UpgradeComponent()
{
slot.GetComponent<BaseComponent>().Upgrade();
}

Unity 3D: Should I make an extensive script or multiple smaller ones for in game items?

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.

Open-Close principle about new features

There is something I do not understand about open-close principle. Let's say that you have done this code:
public abstract class Player
{
public string Name { get; set; }
public int Level { get; set; }
}
public sealed class Fighter : Player { /* ... */ }
public sealed class Warrior : Player { /* ... */ }
This code works perfectly, you've done a first release, eveyrthing is OK.
Now you want to add some features, like a player can equip a ring. Open-close principle says open to extension, close to modification. How could I implement the fact that my players can have rings if I shouldn't modify these class?
You can modify class Player by adding new methods and fields. It is open to extension. But if you already have some methods like Jump or Fight and you want to modify them - that is breaking the principle.
Imagine, your class Fighter has method Fight() and it uses only bare hands:
public Fighter() : Player
{
...
public virtual void Fight()
{
//use bare hands
}
}
If you want Fighter to fight with a stick (for example) you should not modify initial method Fight() but add another class like FighterWithStick : Fighter and override method Fight() there:
public FighterWithStick() : Fighter
{
...
public override void Fight()
{
//use stick
}
}
First think why this kind of rule might be useful. Closed to modification, open to extension. This makes sense for libraries or code that must be backwards compatible. Think of this example:
I've written "BestLibrary" library which exposes interface:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
}
}
But in the next release I want to decide what Goodies to give based on a parameter, so I change the interface to:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
public enum GoodiesType { All, Type1, Type2 }
Now everyone who uses my library has to fix their code, because their projects will stop building. This brakes Open/Closed principle. Instead I should make another method, like this:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
Here I didn't modify anything. Old code still works. Someone wants random Goodies? They can still get it. I extended GoodStuff interface with additional method. This way everything compiles and people can use new functionality.
If you work on a project that is not a library or api, then I don't see any reason to follow this principle. Requirements change and code should follow.

Delegation vs exposing properties

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.

C#: Define methods implementation in base class and properties in derived classes

I am making a game in which I have many kinds of soldiers, each kind with their own attributes (speed, attackPower...). Obviously, all of them can Walk, Attack... so I thought that creating an abstract class Soldier with those methods, and subclasses with each unit attributes would be the appropiate. The problem is that I can't use the attributes of derived classes in the base one.
The easy way would probably be implementing the methods in the derived classes, but that would mean lots of duplicated code, and I want to avoid it. In fact, this would make the base class unneccesary.
I have tried several things. As I understand, the closest solution I tried was using abstract/virtual properties, but again I would be duplicating the "get" code for each unit type. Maybe this can't be avoided, but I'd like to, if possible.
There surely exist a simple solution I haven't thought about. ¿Any ideas?
I think about somethink like this:
public abstract class Soldier {
public int AttackPower {
get { return this.power; }
}
public Attack {
Console.WriteLine("Attacked with "+AttackPower+" attack power");
}
}
public class Lancer:Soldier {
int power=5;
}
public class Archer:Soldier {
int power=10;
}
Of course, this is not a correct solution, because the Soldier class doesn't know about the "power" variable, but if I declare the "power" variable in the Soldier class, I get an error because the field name is duplicated.
Any help will be appreciated.
You need an abstract property:
public int AttackPower {
get { return this.power; }
}
protected abstract int Power { get; }
public class Lancer:Soldier {
protected override int Power { get { return 5; } }
}
You could also do a "GetPower" method if you really don't like properties. As you've discovered, if a base class method needs access to the data, you have to declare that data in the base class.
Its not code duplication, its type safety!
Why not just put a Power property in the base class?
public abstract class Soldier {
public int Power {get; set;}
public int AttackPower {
get { return this.Power; }
}
public Attack {
Console.WriteLine("Attacked with "+AttackPower+" attack power");
}
}
public class Lancer:Soldier {
public Lancer()
{
Power = 5
}
}
public class Archer:Soldier {
public Archer()
{
Power=10;
}
}
Some design comments:
Do you need different classes for Archer and Lancer, or can they just be Soldiers that are configured differently?
It would be better to pull property values like this from a data source rather than hard-coding them in the source code. You can embed an XML file or something so it's not easily editable.

Categories

Resources