0

This is a code for MonoGame 3.8.1 and .NET 6.

public interface IEntity
{
    int Size { get; }
    Vector2 Position { get; }
}
public class Player : IEntity
{
    public int Size { get; } = 32;
    public Vector2 Position { get; private set; }

    public Player(Scene scene)
    {
        var spawnOffset = new Vector2(0, -3);

        Position = new Vector2(
            spawnOffset.X * scene.TileSize + scene.Room.Center.x - Size / 2,
            spawnOffset.Y * scene.TileSize + scene.Room.Center.y - Size / 2);
    }
}
public class Enemy : IEntity
{
    public int Size { get; } = 32;
    public Vector2 Position { get; private set; }

    public Enemy(Scene scene)
    {
        var spawnOffset = new Vector2(0, 0);
    
        Position = new Vector2(
            spawnOffset.X * scene.TileSize + scene.Room.Center.x - Size / 2,
            spawnOffset.Y * scene.TileSize + scene.Room.Center.y - Size / 2);
    }

}

Without the use of inheritance, I want every class that implements IEntity to be able to reuse calculations for Position assignment. The only difference between both constructors is the spawnOffset values.

What's the most simple way to do this?

Normally - I would call the base class constructor, but here I'm trying to do this without a base class.

1 Answer 1

0

Looks like you follow "prefer composition over inheritance" - indeed that is a valid approach, just finish that by extracting "position" functionality into separate class:


class EntityPosition
{
    public Vector2 Position { get; private set; }
    public EntityPosition (Scene scene, Vector2 spawnOffset, int size)
    {
       Position = new Vector2(
        spawnOffset.X * scene.TileSize + scene.Room.Center.x - size / 2,
        spawnOffset.Y * scene.TileSize + scene.Room.Center.y - size / 2);
    }
    // add other shared methods for position updates here as necessary
}

public class Player : IEntity
{
    EntityPosition position;
    public int Size { get; } = 32;
    public Vector2 Position => position.Position;

    public Player(Scene scene)
    {
        var spawnOffset = new Vector2(0, -3);

        position = EntityPosition(scene, spawnOffset, Size);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

One note I will add: Position within the helper class EntityPosition should be { get; set; } not { get; private set; }. Written as-is, classes, such as Player, cannot modify Position, which was not the original intention. If, in truth, the intention was not to be able to modify Position after initialization, then private set; can and should be left out entirely.
@Adam I'd argue that such updates should be implemented by EntityPosition class so all types using it would behave in the same way (as comment in that class suggests). Making position settable in that class will break responsibility boundary that the class sets.
I accept that argument.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.