Class Structure Question

Hello again folks.

I realise this is a general coding question and not a specific MonoGame issue, but you folks do a lot of this coding lark and I’d sooner ask people who actually work at this rather than ask a forum of VS specialists who would answer with the “correct” VS way of coding.

The issue…

Say I have a whole bunch of sprites bouncing around the screen. Some are blue, some are red. Some are orange and some are pink.

All of these different ‘types’ of sprite have basic properties, velocity, position, spin, width, etc.
The orange sprites behave differently and have extra properties, spin2, target, etc.

So I thought I’d create a ‘base’ class that would hold all the common properties the sprites have.
Public Class Basics
Private property c_Velocity
etc.
(Please assume I’ve also completed the property code)

Now in the orange class I can say
Import Basics
Private Property c_Spin2
Private Property c_Drift
etc.

Now orange has all the basic properties and Spin2. I’ve saved a whole load of time as I’m not repeating all the common stuff.

But now I have the problem of remembering which is which, and the code in the parent classes looks untidy. Example:
Private Sub SpinMe
With Me
.Basics.Spin+=1
.cSpin2-=1
.Basics.Position+=cDrift
etc.

I hope you can see where I’m coming from. If someone handed me this to bug test, I’d be a bit confused!

All the classes, once I’ve cleaned them up, will be completely self contained so there won’t be tons of code in Game1 that looks confusing.

So the question is; would you folks put every property in all your classes and have loads more code (in the case of this app hundreds of lines of properties in each class) or put all properties, used or not, in the Basics class and save all that code writing? Or go with this hybrid version?

Please comment as you see fit!
(My previous coding years weren’t big on classes as they really weren’t required often, and certainly not this inheritance stuff)

Thanks.

You can use inheritance to get it cleaner:

Class MyBaseThing
    // shared properties and logic
    Private Property c_Velocity
End Class
Class MyOrangeThing Inherits MyBaseThing
    // orange specific properties and logic
    Private Property c_Spin2
End Class

Then you can create a MyOrangeThing and use the properties in the base class as well.

Use object inheritance for your first game. Learn ECS for your second game.

1 Like

What is ECS? Google returns a very badly written page that doesn’t explain anything. ??

Ahhh, it’s Inherits I’ve been missing!!

Thank you. :slight_smile:

You can use virtual classes to lessen code in child classes placing common code or variables in the base class allows that to be inheirited by child classes derived from them.
Then you need to only add the specific code to derived classes that only they will require.

You can use generics as well with child classes derived from base classes.
For example the following output is generated by the below example Test.

base class instance of Virtual_cs

class instance of A : Virtual_cs {X:0 Y:0}

base class instance of Virtual_cs class instance of B : Virtual_cs {X:1 Y:1} and some additional note in b or call

base class instance of Virtual_cs

Console.Writeline will output the above for each of the 4 items M0 properties that were added to the list. Even though the list is of the base type the child property’s will be called that are overridden.
Of particular note is that class b will return both its base class M0 properties text and its own because the base property has been overriden yet within it calls to the base property as well.
Class C has no M0 property so it will call its base implementation.

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Example
{
    public class Test
    {
        public Test()
        {
            List<Virtual_cs> thelist = new List<Virtual_cs>();
            
            thelist.Add(new Virtual_cs());
            thelist.Add(new A_cs());
            thelist.Add(new B_cs());
            thelist.Add(new C_cs());

            foreach (Virtual_cs i in thelist) 
            {
                Console.WriteLine(i.M0);
            }
        }
    }

    public class Virtual_cs
    {
        public Vector2 position = new Vector2();
        public Virtual_cs()
        {
        }
        private string text = "base class instance of Virtual_cs ";
        public virtual string M0
        {
            get
            {
                return text;
            }
            set
            {
                text = value;
            }
        }
    }
    public class A_cs : Virtual_cs
    {
        public A_cs()
        {
        }
        private string text = "class instance of A : Virtual_cs ";
        public override string M0
        {
            get
            {
                return text + position.ToString();
            }
            set
            {
                text = value;
            }
        }
    }
    public class B_cs : Virtual_cs
    {
        public B_cs()
        {
        }
        private string text = "class instance of B : Virtual_cs ";
        public override string M0
        {
            get
            {
                position = Vector2.One;
                return base.M0 + text + position.ToString() + " and some additional note in b or call";
            }
            set
            {
                text = value;
            }
        }
    }
    public class C_cs : Virtual_cs
    {
        public C_cs()
        {
        }
    }
}

The only cavet to this is that you can’t call to specific variables or methods from a generic container unless they are declared in the base class, or without back casting the object in the list to the child class that was added to the generic container. In the case of update and draw however you can use the default behavior or child specific behavior.

One problem with a system where each entity has it’s own class style inheritance is it prevents you from being able to code an ability once and share it to multiple types of entities. One way to handle this would be to put the behaviors that are different between entities into classes (components) that all inherit from the same base class. Then you can keep a list of them in the entity and iterate over the list and either check for a spin me component and then do the spinning, or put the spinning code directly in the spin class.

Here’s an article that I skimmed and seemed to look good: https://www.raywenderlich.com/24878/introduction-to-component-based-architecture-in-games

Also it’s not that bad to just keep all the properties like you have now and find other ways of tidying up the code, even having an if Type == Type.Orange surrounding the bits only the orange guy uses might make it clearer.

I often use a delegate in the base class to specialize “behaviors” in the children classes.
Less code in child classe, and behaviors can be centralized in one file.

For those interested see component pattern.