Static image variable across multiple classes - c#

I'm currently working in C#, and I have a base class (bullet) that is required to have a variable and subsequent getter (image) because another class expects that behavior (powerup) in order to display properly. Bullet will then be extended to make many different bullets with varying behavior. however, every bullet extension class needs only one image per class (not per instance) because it will never need to change between bullets of similar class, and there will be hundreds of them on screen, so space is an issue. ie, I need an object in a base class, that is then static in extensions from that class. Is there any way to create this in C#, and if not, out of curiosity, any other object oriented language?
Many Thanks
edit:
for example:
class bullet{
public Image Level
{
get { return image; }
set { image = value; }
}
}
class spiralBullet : bullet{
static var image = "spiralbullet";
}
class largeBullet : bullet{
static var image = "largebullet";
}
except somehow, the getter returns the correct static image for each class

Define an abstract property Getter on your base class.
In the derived class, have a private static Image field.
Override the abstract property Getter and return your static image field.
public abstract class Bullet
{
public abstract Image Image { get; }
}
public class SquareBullet : Bullet
{
private static Image _image /* = Load your image */;
public override Image Image
{
get
{
return _image;
}
}
}
Alternatively, if the Image is a simple hard-coded value:
public abstract class Bullet
{
public abstract string Image { get; }
}
public class SquareBullet : Bullet
{
public override Image Image
{
get
{
return "Square";
}
}
}
The advantage here, if it's suitable, is that the value "Square" exists in a code segment, not a data segment, and is 'static' (or shared) by definition.

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();
}

The correct way to change the base class from derived class

I am trying to design several base drawing classes from which I can inherit and define complex drawings. In the code below, you can see that LineDrawing and CompoundDrawing derive from an abstract Drawing class. The CompoundDrawing class has an internal List<Drawing> that allows us to store multiple Drawing objects and define complex drawings.
public abstract class Drawing
{
public bool CanBeRotated
{
get;
set;
}
private float m_rotation;
public float Rotation
{
get
{
return m_rotation;
}
}
protected Drawing()
{
CanBeRotated = true;
}
public void Rotate(float degree)
{
if (CanBeRotated)
m_rotation = degree;
}
}
public sealed class LineDrawing : Drawing
{
private readonly Line m_line;
public Line Line
{
get
{
return m_line;
}
}
public LineDrawing(Line line)
{
m_line = line;
}
}
public class CompoundDrawing : Drawing
{
protected IList<Drawing> m_drawings;
protected CompoundDrawing(IList<Drawing> drawings)
{
m_drawings = new List<Drawing>(drawings);
}
}
Now I want to define a RectangleDrawing class that derives from CompoundDrawing. Here is the code for this class:
public class RectangleDrawing : CompoundDrawing
{
public RectangleDrawing(IList<LineDrawing> lineDrawings) : base(lineDrawings)
{
foreach(var line in lineDrawings)
{
line.CanBeRotated = false;
}
}
}
The problem I am facing is that the LineDrawing objects in the RectangleDrawing class should not be rotatable, but I'm not sure where in my design pattern I should set this restriction. How can I prevent the LineDrawing objects in RectangleDrawing from being rotatable?
I'd move the Rotate to its own interface since it wouldn't be valid for all kinds of drawing.
public interface IRotate
{
void Rotate(float degree);
}
public class SquareDrawing : Drawing, IRotate
{
public void Rotate(float degree)
{
//actual code to rotate the drawing
}
}
public class RectangleDrawing : CompoundDrawing
{
public RectangleDrawing(IList<LineDrawing> lineDrawings) : base(lineDrawings)
{
foreach(var line in lineDrawings)
{
if (line is IRotate)
{
((IRotate)line).Rotate(45.0);
}
}
}
}
I would consider taking an immutable approach:
public abstract class Drawing
{
//some shapes might not be rotable or rotation
//simply doesn't make sense: circle
public virtual bool CanBeRotated => true;
public Drawing Rotate(float degree)
{
//Don't mutate this, return a new
//rotated instance.
if (!CanBeRotated) return this;
return rotate(float);
}
//let each concrete type handle its own rotation.
protected abstract Drawing rotate(float);
//etc.
}
What does immutability buy you? Well, who cares if someone tries to rotate and individual line of your compound object? They won't change anything significant because nothing can change, they will simply obtain a new rotated line that doesn't belong to the original compound object.
And the CompoundDrawing rotation logic would be rather simple:
protected override Drawing rotate(float degeee)
//Note I'm passing in an IEnumerable<Line> instead of an IList<>
//Why the need of an IList<>, don't burden the API with unecessary
//constraints.
=> new Rectange(lines.Select(l => l.Rotate(degree)));
All this said, I'd recommend you change your building block to Point, Line seems like a weird choice. This way all shapes are compound drawings made up of points in a specific order. Drawing any shape is simply connecting the points in order, rotating is simply rotating every point, etc.

Automatically create a copy of a static variable for each derived class

I have a base class with a static variable. I want to create derived subclasses which will automatically have their own unshared static variable. Ideally it would look like this:
class Parent
{
Texture2D picture;
static Texture2D pictureOrigin;
Parent()
{
picture = pictureOrigin;
/*Loading the static origin to an instance variable
because I might want to have more pictureOrigins
and alternate them or perhaps change the picture
of the instance based on a certain event, etc.*/
}
}
class Subclass1 : Parent
{
Subclass1() : base()
{ }
}
class Subclass2 : Parent
{
Subclass2() : base()
{ }
}
void main()
{
Parent.pictureOrigin = Load("pictureForParent");
Subclass1.pictureOrigin = Load("pictureForSubclass1");
Subclass2.pictureOrigin = Load("pictureForSubclass2");
//Then creating instances of the classes and drawing them, etc.
}
But what happens is that they all get the last loaded image (pictureForSubclass2) because the static variable pictureOrigin is shared between them.
The quickest fix is manually adding new static variable pictureOrigin to each subclass and hiding the pictureOrigin variable of the base class:
class Subclass1 : Parent
{
new static Texture2D pictureOrigin;
Subclass1() : base()
{
picture = pictureOrigin;
}
}
Alternatively, creating abstract methods or similar to ensure the creation of the new static variable in the subclasses. But it seems like too much of a hassle and not too elegant. Is there a better way of doing this?
Your question smells like a poor design. Static variables are generally poor practice in my opinion, and proper object-oriented design can eliminate the need to ever use static members.
Try refactoring like so:
public class Parent
{
private Texture2D texture;
public Parent(Texture2D texture) {
this.texture = texture;
}
public Texture2D Picture { get {
return texture;
}
}
}
public class SubClass1 : Parent
{
public SubClass1(Texture2D texture) : base(texture) {
}
}
Let me elaborate on why static is a poor choice:
Your class is now only good for a single bitmap. Eliminates the possibility to reuse a class for several bitmaps (this is the limitation you're fighting against)
Your class is not in a valid state until the static setter is called. Generally objects, once constructed, should be in a valid state. It won't be obvious to others if they're using your object that they have to statically set the bitmap on the class.
Breaks the natural garbage collection. For example if you wanted the Texture2D object to be garbage collected when all the instances of SubClass are collected it wouldn't work with your static design. Alternatively, if you use a oop design (like suggested) you have the flexibility to garbage collect or not depending on your use cases.
Makes threading more complicated. Statics are global, so you need global mutexes to guarantee thread-safety.
Makes testing more difficult. If you want to unit test the class, you have to make sure that the static is cleaned up after every test, and you couldn't run two unit tests against this class in parallel.
Makes memory management inflexible. If you use object-oriented design you can choose to share bitmaps among all instances, or allocate a new bitmap for every instance.
You can do this with a static Dictionary<Type,Texture2D>.
public class Parent
{
// Keep a table of types and default values
protected static Dictionary<Type, Texture2D> pictureOrigin;
static Parent()
{
// static ctor. initialize table
pictureOrigin=new Dictionary<Type, Texture2D>();
}
internal static void SetDefaultPicture<T>(Texture2D picture)
{
// Set default based on type T
Type type=typeof(T);
pictureOrigin[type]=picture;
}
public Parent()
{
// Assign default based on this type
Picture=pictureOrigin[this.GetType()];
}
public Texture2D Picture { get; set; }
}
public class SubClass1 : Parent
{
}
public class SubClass2 : Parent
{
}
to be used as
static void Main(string[] args)
{
Texture2D picture0 = Load("pictureForParent");
Texture2D picture1=Load("pictureFroSubClass1");
Texture2D picture2=Load("pictureFroSubClass2");
Parent.SetDefaultPicture<Parent>(picture0);
Parent.SetDefaultPicture<SubClass1>(picture1);
Parent.SetDefaultPicture<SubClass2>(picture2);
}
Here is the debug of an example. It shows that SubClass1 initialized with pictureForSubClass1 automatically.
A static member that declared in generic type is basically declared per class and its generic.
For example Foo<Bar>.baz is not equal to Foo<Qux>.baz.
So basically you can do this:
abstract class Parent<T>
{
Texture2D picture;
static Texture2D pictureOrigin;
Parent()
{
picture = pictureOrigin;
/*Loading the static origin to an instance variable
because I might want to have more pictureOrigins
and alternate them or perhaps change the picture
of the instance based on a certain event, etc.*/
}
}
class Parent : Parent<Parent>
{
Parent () : base()
{ }
}
class Subclass1 : Parent<Subclass1>
{
Subclass1() : base()
{ }
}
class Subclass2 : Parent<Subclass2>
{
Subclass2() : base()
{ }
}
void main()
{
Parent.pictureOrigin = Load("pictureForParent");
Parent<Subclass1>.pictureOrigin = Load("pictureForSubclass1");
Parent<Subclass2>.pictureOrigin = Load("pictureForSubclass2");
}

How to cache static data for classes with use of inheritance?

Imagine you're making a game object that is using some texture:
public class Action {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/select";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public static Texture2D cursor { get { return ResourceManager.loadTexture(ref cursorTex, HoverCursor); } }
}
The loadTexture function will load the texture if null is passed. otherwise, it just returns the original value.
As you can see, I'm making an Action prototype. There will be actions like Attack, Move or Build. I want to store one (and different) texture object per class definition. This object shall be lazy-loaded when needed using the getter above.
Since the static property can't be overriden, how can I implement this for all children instances?
Here's the loadTexture:
public static Texture2D loadTexture(ref Texture2D target, string name)
{
if (target == null)
{
target = (Texture2D)Resources.Load(name, typeof(Texture2D));
}
return target;
}
You can use inheritance and polymorphism with instance members, and use a static factory method as a façade to simplify the instantiation of the implementation.
For example
public abstract class Action
{
public abstract void LoadTexture(...);
}
// Since static façade class has a generic type parameter, we're talking
// about a completely different class than just "Action" and both can co-exist!
public static class Action<TAction> where TAction : Action, new()
{
public static Texture2D LoadTexture(...)
{
// Since generic TAction parameter must implement a public parameterless
// constructor, you may instantiate T like a concrete class:
return new TAction().LoadTexture(...);
}
}
Thus, you would use the static method as follows:
Texture2D texture = Action<CustomAction>.LoadTexture2D(...);
You've practically answered the question yourself:
Since the static property can't be overriden, how can I implement this for all children instances?
Just make the property an instance property. For example:
public class Action {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/select";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public virtual Texture2D cursor
{
get
{
return ResourceManager.loadTexture(ref cursorTex, HoverCursor);
}
}
}
public class Attack {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/attack";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public override Texture2D cursor
{
get
{
return ResourceManager.loadTexture(ref cursorTex, HoverCursor);
}
}
}
You would still save just one texture per class, but given an instance of each class you'll be able to retrieve the correct cursor texture for that class. Presumably you need to set the cursor only when there's an instance of the class around anyway, so this shouldn't be an unreasonable limitation.
Note in the above that if no other code actually needs the HoverCursor property, you can get rid of it, make the _HoverCursor const a private member, and then use that directly in the cursor property getter.
Also note that this implementation isn't thread-safe. As long as you're always accessing the cursor property from a single thread, that's fine. But if not (or perhaps just for the simplicity) you may prefer using the Lazy<T> class. For example:
//This is the get texture by string
private static Lazy<Texture2D> cursorTex =
new Lazy<Texture2D>(() => ResourceManager.loadTexture(HoverCursor));
public virtual Texture2D cursor
{
get
{
return cursorTex.Value;
}
}
In this version, note that the loadTexture() method has changed to always load the texture, and thus does not need the ref parameter. The Lazy<T> class will ensure thread-safe lazy initialization, calling loadTexture() only once per class.

Using Generics to Access Classes in an XNA Game

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.

Categories

Resources