Separacja warstw w grze

0

Piszę grę w której chciałbym oddzielić logikę od renderingu - obecnie mam 2 projekty: Logic oraz Rendering.
W projekcie Logic mam coś w stylu:

public interface IItemHelper
{
  IsInRange(Player player, Item item)
}

public class Player
{
  private IItemHelper itemHelper;

  public bool TryPickUp(Item item)
  {
    if (!itemHelper.IsInRange(this, item))
	  return false;
	//pozostałe sprawdzanie
  }
}

W projekcie Rendering mam adaptery opakowujące elementy w stylu:

public class Sprite<T>
{
  public T LogicElement { get; private set; }
  public Vector2 Position { get; set; }
  
  public Sprite(T logicElement) 
  {
    LogicElement = logicElement;
  }
  //pozostał właściwości potrzebne do rysowania
}

public class ItemAdapter : Sprite<Item>
{
  public ItemAdapter(Item tem) : base(item) {}
  //medtody związane z renderingiem przedmiotu
}

public class PlayerAdapter : Sprite<Player>
{
  public PlayerAdapter(Player player) : base(player) {}
  //medtody związane z renderingiem gracza
}

Implementacja IItemHelper znajduje się także w projekcie Rendering:

public class ItemHelper : IItemHelper
{
  public IsInRange(Player player, Item item)
  {
    var playerAdapter = GetAsAdapter(player);
	var itemAdapter = GetAsAdapter(item);
	
	return Math.Distance(playerAdapter.Position, itemAdapter.Position) < 2
  }
}

Problem dotyczy właśnie GetAsAdapter - nie za bardzo wiem w którą stronę z tym iść. Pierwsze rozwiązanie:

  1. Mamy listę Sprite'ów i ją przeszukujemy dopasowując po LogicElement - spriteList.First(s => s.LogicElement == element) - mało eleganckie rozwiązanie i pewnie w dalszej perspektywie mało wydajne.
  2. Elementy logiki trzymają swój Adapter, np.
//Logic
public class Element
{
  object Adapter {get; set;}
}

public class Player : Element { }

//Rendering
public class Sprite<T>
{
  public T LogicElement { get; private set; }
  public Sprite(T logicElement)
  {
    LogicElement.Adapter = this;
  }  
}

Jednak to rozwiązanie również wydaje mi się jeszcze brzydsze, lecz zapewne wydajniejsze.
Macie może pomysły jak mógłbym rozwiązać ten problem? A może zupełnie inaczej powinienem do tego podejść?

1

Adapter to bardzo ogólna nazwa, zmieniłbym ją na coś bardziej specyficznego.

A co do głównego problemu - czemu po prostu nie przechowywać Position w klasie Player i Item (albo w jakiejś ich ogólnej bazowej klasie)?

0

A co do głównego problemu - czemu po prostu nie przechowywać Position w klasie Player i Item (albo w jakiejś ich ogólnej bazowej klasie)?

Rozważałem takie podejście i chyba coraz bardziej się do niego skłaniam. Dlaczego na początku je odrzuciłem? Chciałem, żeby logika pozwalała w łatwy sposób przenieść grę np. z 2d do 3d i wydawało mi się, że takie właściwości jak pozycja, rotacja, skala powinny być tylko po stronie renderingu. Ponadto rozwiązanie będzie wymagać ciągłej konwersji struktury Position na strukturę Vector2.

1 użytkowników online, w tym zalogowanych: 0, gości: 1