Optimizing Fruit Spawning

Code by Ireneusz A.
 avatar
user_6919294
pascal
5 months ago
3.1 kB
8
Indexable
// Hej Daria, ja bym zrobił tak ^_-

type
  // Struktura przechowująca typ owocu i jego prawdopodobieństwo wystąpienia
  TFruitProbability = record
    FruitType: TFruitType;
    Probability: Integer;      // Wartość w promilach (na 1000)
  end;

const
  // Tablica definiująca prawdopodobieństwa wystąpienia każdego typu owocu
  // Wartości sumują się do 1000 (100%)
  FRUIT_PROBABILITIES: array[0..6] of TFruitProbability = (
    (FruitType: ftApple;       Probability: 300),  // 30%
    (FruitType: ftBanana;      Probability: 200),  // 20%
    (FruitType: ftStrawberry;  Probability: 150),  // 15%
    (FruitType: ftOrange;      Probability: 150),  // 15%
    (FruitType: ftGrape;       Probability: 100),  // 10%
    (FruitType: ftWatermelon;  Probability: 90),   // 9%
    (FruitType: ftDragonFruit; Probability: 10)    // 1%
  );

{*
  Funkcja losuje typ owocu na podstawie zdefiniowanych prawdopodobieństw
  @return Wylosowany typ owocu
*}
function GetRandomFruitType: TFruitType;
var
  RandomValue, AccumulatedProb: Integer;
  I: Integer;
begin
  // Losujemy liczbę z zakresu 0-999
  RandomValue := Random(1000);
  AccumulatedProb := 0;
  
  // Przechodzimy przez tablicę prawdopodobieństw, sumując je
  // aż znajdziemy przedział, w którym mieści się wylosowana liczba
  for I := Low(FRUIT_PROBABILITIES) to High(FRUIT_PROBABILITIES) do
  begin
    Inc(AccumulatedProb, FRUIT_PROBABILITIES[I].Probability);
    if RandomValue < AccumulatedProb then
      Exit(FRUIT_PROBABILITIES[I].FruitType);
  end;
  
  // Zabezpieczenie - gdyby coś poszło nie tak, zwracamy ostatni typ owocu
  Result := FRUIT_PROBABILITIES[High(FRUIT_PROBABILITIES)].FruitType;
end;

{*
  Procedura tworzy nowy owoc lub przenosi istniejący w nowe miejsce
  Odpowiada za:
  - Wylosowanie typu owocu zgodnie z zadanymi prawdopodobieństwami
  - Utworzenie lub aktualizację instancji owocu
  - Umieszczenie owocu w losowej pozycji na planszy
*}
procedure TMainForm.SpawnFood;
var
  NewFruitType: TFruitType;
  NewPosition: TPointF;
begin
  // Losujemy nowy typ owocu według zdefiniowanych prawdopodobieństw
  NewFruitType := GetRandomFruitType;

  // Jeśli nie mamy owocu lub typ się zmienił, tworzymy nową instancję
  if (not Assigned(FCurrentFruit)) or (FCurrentFruit.FruitType <> NewFruitType) then
  begin
    // Bezpiecznie zwalniamy poprzedni owoc (jeśli istniał)
    FreeAndNil(FCurrentFruit);
    // Tworzymy nowy owoc i ustawiamy jego rodzica
    FCurrentFruit := TFruit.Create(Self, NewFruitType);
    FCurrentFruit.Parent := GameRec;
  end;

  // Obliczamy nową pozycję, upewniając się, że owoc nie wyjdzie poza granice
  // Max(0, ...) zapewnia, że pozycja nie będzie ujemna
  NewPosition.X := Max(0, Random(Round(GameRec.Width - FCurrentFruit.Width)));
  NewPosition.Y := Max(0, Random(Round(GameRec.Height - FCurrentFruit.Height)));
  
  // Ustawiamy obliczoną pozycję
  FCurrentFruit.Position := NewPosition;
end;

// Nie ma za co, pozdrawiam Irek. 
Editor is loading...
Leave a Comment