No strategia tu pasuje.
Stwórz sobie ogólna klasę "Script" (może być abstrakcyjna) w której będzie wszystko co potrzebne do uruchomienia skryptu (czyli pewnie jedna funkcja). Następnie stwórz klasy odpowiedzialne za konkretne implementacje skryptów, które dziedziczą po "Script", np "ScriptA".
No i tworzysz funkcje w której w switchu będziesz sobie wybierał obiekt którego algorytmu stworzyć a następnie wywołujesz. To jest najprostsze, lopatologiczne rozwiązanie.
Pewnie tak, ale jak rozumiem, wtedy musi istnieć zamknięta, odgórnie zdefiniowana lista takich skryptów, a mi chodzi o coś bardziej ala pseudo język skryptowy, gdzie trzymając się ogólnej struktury danej funkcji, mogę ją sobie dowolnie modyfikować.
Może na przykładzie, żeby przedstawić do czego mi to konkretnie potrzebne. Chodzi o silnik gry, w którym logika gry jest odświeżana niezależnie od renderowania (oba mają własne wątki i własne pętle), ale współdzielą pewne informacje.
Logika gry jest karmiona kodem poprzez abstrakcyjną metodę Update()
, która jest nadpisywana zależnie od gry. Załóżmy wiec, że świecie gry istnieje jakiś tam Object
, który ma pole Value
, a między kolejnymi aktualizacjami logiki wartość ta musi wzrosnąć o 60
, a więc:
void Update() override
{
Object.Value.Set(Object.Value + 60);
}
Słowem wyjaśnienia. Value
to instancja klasy szablonowej, która jest wrapperem dla prostego typu (int, float, char itd., reszta jest wykluczona przy pomocy conceptów). Wywołanie Set()
nie tylko aktualizuje wartość zmiennej, ale też zakulisowo generuje i kolejkuje instrukcje dla Renderera, który posiada własną kopię wszystkich obiektów świata podlegających rysowaniu. Standardowa instrukcja wygląda tak (po wykonaniu kilku wstępnych wyliczeń):
void Script(auto& This, const float& fDelta)
{
This.Value = This.OldValue + (This.Factor * fDelta);
//Factor to wyliczony współczynnik przesunięcia, różnica między starą i nową wartością, w tym przypadku 60.
//Delta to oczywiście współczynnik upływu czasu rzeczywistego liczony w sekundach i mieszczący się w przedziale 0.0f - 1.0f.
}
Dzięki takiej konstrukcji, Renderer może interpolować miedzy starą a nową wartością i rysować klatki pośrednie (bo na jeden update logiki gry zwykle przypada wiele klatek). Tyle tylko, że taka "ślepa" interpolacja nie zawsze się sprawdza, np. w przypadku portali czy nagłych przesunięć obiektów (których przemieszczenie nie jest rozłożone w czasie i muszą natychmiastowo przejść od jednej wartości do drugiej).
I tu właśnie pojawia się możliwość nadpisania skryptu standardowego przy pomocy lambdy. Np.
void Update() override
{
Object.Value.Set(Object.Value + 60);
Object.Value.SetRenderScript
(
[](auto& This, const float& fDelta)
{
if (n::World[Skeleton67].PosX.Value > 123) This.Value = n::World[Tree11].PosY.Value * fDelta;
//n::World to statyczny wskaźnik na instancję świata, którą włada Renderer. Dzięki temu jest dostępny z wnętrza lambdy.
}
);
}
Chodzi o możliwość korygowania pewnych sytuacji, w których zwykła interpolacja nie wystarcza. Z tego co czytałem, normalnie coś takiego wymaga implementacji języka skryptowego, ale to sporo roboty, więc szukam drogi na skróty :).