Zoeken…


Kaart implementeren in RPG-spel

Vlieggewicht is een van de structurele ontwerppatronen. Het wordt gebruikt om de hoeveelheid gebruikt geheugen te verminderen door zoveel mogelijk gegevens met vergelijkbare objecten te delen. Dit document leert u hoe u Flyweight DP op de juiste manier kunt gebruiken.

Laat me het idee ervan aan u uitleggen aan de hand van een eenvoudig voorbeeld. Stel je voor dat je aan een RPG-game werkt en dat je een enorm bestand moet laden dat enkele karakters bevat. Bijvoorbeeld:

  • # is gras. Je kunt erop lopen.
  • $ is het startpunt
  • @ is rock. Je kunt er niet op lopen.
  • % is schatkist

Voorbeeld van een kaart:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@############@@@@@######@#$@@@

@#############@@@######@###@@@

@#######%######@###########@@@

@############################@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Aangezien deze objecten vergelijkbare kenmerken hebben, hoeft u geen afzonderlijk object voor elk kaartveld te maken. Ik zal je laten zien hoe vlieggewicht te gebruiken.

Laten we een interface definiëren die onze velden zullen implementeren:

public interface IField
{
    string Name { get; }
    char Mark { get; }
    bool CanWalk { get; }
    FieldType Type { get; }
}

Nu kunnen we klassen maken die onze velden vertegenwoordigen. We moeten ze ook op de een of andere manier identificeren (ik heb een opsomming gebruikt):

public enum FieldType
{
    GRASS,
    ROCK,
    START,
    CHEST
}
public class Grass : IField
{
    public string Name { get { return "Grass"; } }
    public char Mark { get { return '#'; } }
    public bool CanWalk { get { return true; } }
    public FieldType Type { get { return FieldType.GRASS; } }
}
public class StartingPoint : IField
{
    public string Name { get { return "Starting Point"; } }
    public char Mark { get { return '$'; } }
    public bool CanWalk { get { return true; } }
    public FieldType Type { get { return FieldType.START; } }
}
public class Rock : IField
{
    public string Name { get { return "Rock"; } }
    public char Mark { get { return '@'; } }
    public bool CanWalk { get { return false; } }
    public FieldType Type { get { return FieldType.ROCK; } }
}
public class TreasureChest : IField
{
    public string Name { get { return "Treasure Chest"; } }
    public char Mark { get { return '%'; } }
    public bool CanWalk { get { return true; } } // you can approach it
    public FieldType Type { get { return FieldType.CHEST; } }
}

Zoals ik al zei, we hoeven geen afzonderlijke instantie voor elk veld te maken. We moeten een repository met velden maken. De essentie van Flyweight DP is dat we alleen dynamisch een object maken als we het nodig hebben en het nog niet bestaat in onze repo, of retourneren als het al bestaat. Laten we een eenvoudige les schrijven die dit voor ons afhandelt:

public class FieldRepository
{
    private List<IField> lstFields = new List<IField>();

    private IField AddField(FieldType type)
    {
        IField f;
        switch(type)
        {
            case FieldType.GRASS: f = new Grass(); break;
            case FieldType.ROCK: f = new Rock(); break;
            case FieldType.START: f = new StartingPoint(); break;
            case FieldType.CHEST:
            default: f = new TreasureChest(); break;
        }
        lstFields.Add(f); //add it to repository
        Console.WriteLine("Created new instance of {0}", f.Name);
        return f;
    }
    public IField GetField(FieldType type)
    {
        IField f = lstFields.Find(x => x.Type == type);
        if (f != null) return f;
        else return AddField(type);
    }
}

Super goed! Nu kunnen we onze code testen:

public class Program
{
    public static void Main(string[] args)
    {
        FieldRepository f = new FieldRepository();
        IField grass = f.GetField(FieldType.GRASS);
        grass = f.GetField(FieldType.ROCK);
        grass = f.GetField(FieldType.GRASS);       
    }
}

Het resultaat in de console moet zijn:

Een nieuw exemplaar van Grass gemaakt

Een nieuw exemplaar van Rock gemaakt

Maar waarom verschijnt gras maar één keer als we het twee keer wilden krijgen? Dat komt omdat de eerste keer dat we GetField grass-instantie aanroepen niet bestaat in onze repository , dus het is gemaakt, maar de volgende keer dat we gras nodig hebben, bestaat het al, dus we retourneren het alleen.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow