Programowanie gry - pare pytań

0

Witam szanownych forumowiczów.

Przychodze z paroma pytaniami.
Robię w Delphi grę 2d używając modułu DelphiX. (słyszałem, że są lepsze alternatywy, ale wydaje mi się, że DX starczy)

I mam pare pytań... W grze będzie parenaście postaci ...

type
  TCharacter = class
    Position: TPosition;
    Health, HealthMax: Integer;
    HealthTicks: Integer;
    RegenRate: Integer;
    Frames: array of TFrame;
    CurrentFrame: Integer;
    FrameTicks: Integer;
    ShakeTicks: Integer;
    WalkingSpeedX: Integer;
    WalkingSpeedZ: Integer;
    RunningSpeedX: Integer;
    RunningSpeedZ: Integer;
    JumpSpeed: Integer;
    OutVelocityX: Integer;
    OutVelocityY: Integer;
    OutVelocityZ: Integer;
    function IsShaking: Boolean;
    function NegX(Value: Integer): Integer;
    function GetCurrentFrame: TFrame;
    function Load(Name: String): Boolean;
end;

... do wyboru i w trakcie jej trwania postaci będzie nieco przybywać i ubywać. I teraz pytanie - czy ładować procedurą Load (która czyta z danego pliku XML dane o postaci) za każdym razem kiedy na polu bitwy pojawia się dana postać? Czy może lepiej przed rozpoczęciem gry załadować wszystkie możliwe postacie do jakiejś tablicy, listy i potem w trakcie walki po prostu == z tymi preloadowanymi. Pewnie niedokońca mnie zrozumieliście (słaba umiejętność komunikacji z mojej strony ;P)więc może na przykładach:

Ładowanie w trakcie gry:

var
   NewCharacter: TCharacter;
begin
   NewCharacter := TCharacter.Create;
   NewCharacter.Load(Name);
   { ustawianie pozycji postaci blablablabla }
end;

czy lepiej:

{ przed zaladowaniem gry }
{ charnames = tablica typu string z imionami wszystkich postaci }
{ character data = tablica typu TCharacter zawierajaca wszystkie postacie }
for i:=1 to (length(charnames)-1) do
begin
  NewChar := TCharacter.Create;
  NewChar.Load(charanmes[i]);
  SetLength(CharacterData, Length(CharacterData)+1);
  CharacterData[Length(CharacterData)] := NewChar;
end;

{w trakcie gry tworzenie nowej postaci }

var
   NewCharacter: TCharacter;
begin
   for i := 1 to Length(CharacterData) do
   begin
      if CharacterData[i].Name = Name then
      begin
          NewCharacter.Costam := CharacterData[i].Costam
          { i tak wszystkie parametry }
          { dlaczego wszystkie parametry? bo to pointery }
      end;
end;

To pierwsze pytanie... drugie - w grze będą postacie i różne obiekty którymi będzie można rzucać; atakować przeciwników oraz ich magiczne ataki (jakieś kule energi i takie tam) - czy robic wszystko pod jedna klasa np. TThing i potem TPlayer = class(TThing) ; TMagicAttack = class(TThing) i rzutowac ( if ShotThing is TPlayer then blablablabla) czy lepiej osobne klasy, osobne warunki i bez rzutowania? W sumie rzutowanie się przyda przy sprawdzaniu kolizji (kod nizej), mozna wtedy sprawdzac czy Thing i Thing sie zderzaja i jesli tak wykonac procedure Thing.OnCollide ktora bedzie overridowana przez klasy TPlayer, TMagicAttack, TWeapon i tam dokonywane beda odpowiednie czynnosci...

Ostatnie pytanie będzie o kolizjach... w jaki sposób je detectować? Sprawdzać co każdy Tick (DXTimerTimer z interval 0) kolizje wszystkich przedmiotow ze wszystkimi? :| mi sie to wydaje okropnie niewydajne....

procedure CheckCollisions;
begin
   for i:=1 to Length(Things) do
   begin
      for j:=1 to Length(Things) do
         if Collides(Things[i], Things[j]) then
             Things[i].Collide(Things[j]);
   end;
end;

function Collides(First, Second: TThing): Boolean;
begin
   { tutaj sprawdzanie czy obiekty na ziebie zachodza, jesli tak to Result := True, jesli nie to Result := False }
end;

Z góry dziękuje za zainteresowanie się tematem.</delphi>

0

Co do pytania pierwszego to musisz zadać sobie pytanie ile pamięci potrzeba na załadowanie wszystkich elementów gry. Jeżeli jest to w granicach rozsądku, to ładuj wszystkie. Jeżeli nie to zastanów się, które elementy będą na pewno, wtedy je ładuj, pozostałe, które mogą być ale nie muszą ładuj na bieŻąco (Boże, widzisz takie błędy i nie grzmisz). Możesz podzielić rozgrywkę na tury, wówczas ładujesz wszystko z danej tury. Poza tym zmierz czas potrzebny na załadowanie jednego elementu. Jeżeli jest on bardzo niewielki, to opłaca się tworzyć na bieżąco (oby nie za często bo gra będzie przycinać).

Co do klasy bazowej to jest to gra warta świeczki. Dobrze zaimplementowana klasa oszczędzi Ci masę pisania i zmniejszy kod. Używaj metod wirtualnych lub dynamicznych. Ja w moim programie dla firmy popełniłem mały błąd. Wynikał on z braku czasu na przeanalizownie zagadnienia. Efektem jest to, że teraz muszę przeklejać spore fragmenty tekstu, bo nie mam zdefiniowanej klasy. Zmierzam do tego, że musisz zastanowić się, jakie elementy będą wspólne dla klas potomnych. Kiedyś pisałem program do morphingu w Turbo Pascalu. Klasa bazowa TFigura zawierała wszystkie elementy wspólne: morphing, obroty, wyświetlanie pikseli. Jedyne czym się różniły to konstruktorem bo inaczej wygląda kula, a inaczej sześcian.

Dodatkowo moge polecić książkę Piotra Besty "Tworzenie gier 2D/3D w Turbo Pascalu". Jest tam sporo ciekawostek.

Co do kolizji to na forum jest gotowiec z kolizjami w DX. Nie polecam timera z intervalem na 0 bo po co. Jeżeli leci pocisk to steruje nim pętla i warunek sprawdzasz w kroku pętli. Jeżeli sterujesz człowiekiem, to przemieszczasz go strzałkami, czyli sprawdzasz kolizję w momencie naciśnięcia klawisza ruchu.

Powodzenia w grze. Adam. :-)

0

"Poza tym zmierz czas potrzebny na załadowanie jednego elementu. Jeżeli jest on bardzo niewielki, to opłaca się tworzyć na bieżąco (oby nie za często bo gra będzie przycinać)."

No właśnie w tym rzecz, że u mnie się raczej nie będzie przycinało, ale nie wszyscy dysponują szybkimi komputerami (mój też nie jest nie wiadomo jak szybki- 2,4; ale nie chce aby gra 2d z kilkoma spritami sie ciela np. na jakims 566 mhz z akceleratorem :S)

"Co do kolizji to na forum jest gotowiec z kolizjami w DX."
No właśnie mam trochę kłopot z jego obsługą :P Myśle, że sprawdzanie ręczne lepiej wyjdzie (zwłaszcza, że to nic trudnego sprawdzić czy 2 prostokąty na siebie zachodzą).

"Nie polecam timera z intervalem na 0 bo po co."
Chociażby do rysowania na DXDraw... mógłbym zrobić program w pętli, ale po co?

"Jeżeli leci pocisk to steruje nim pętla i warunek sprawdzasz w kroku pętli. Jeżeli sterujesz człowiekiem, to przemieszczasz go strzałkami, czyli sprawdzasz kolizję w momencie naciśnięcia klawisza ruchu."
Mówiąc 'sprawdzasz kolizje' masz na myśli "przejechanie" pętlą FOR wszystkich elementów i sprawdzenie czy collision-box danego elementu zachodzi na poruszany obiekt? Na nic bardziej zoptymalizowanego nie wpadłem :/

Dziękuje bardzo za zainteresowanie się moim problemem ;)

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