Gra statki - jakiego komponentu użyć do zrobienia siatek pól

0

Witam.
Potrzebuję zrobić grę w Lazarusie - statki. Szukam komponentu który odzwierciedliłby mi pole gracza i pole komputera.
Myślałem wstawić...200 TShapeów obok siebie ale to byłoby beznadziejne.

2

Wystarczy jeden PaintBox, rysujesz sam co zechcesz.

0

Dodam tylko, że jeśli nie chcesz lub nie umiesz tego zrobić w TPitureBox to możesz wykorzystać TStringGrid i własne rysowanie.

0

Wystarczy TPanel oraz jakiś silnik obsługujący OpenGL*; jako handle do silnika podajesz handle kontrolki i voilà.
* nie jestem pewien, czy DirectX również na takie rzeczy pozwala.

0

pobierz pakiet BGRAControls, jest tam komponent (wraz z przykładem) BCGameGrid: http://wiki.freepascal.org/BGRAControls#BCGameGrid

0

Próbowałem z tym TPaintBox i jakoś mi nie chce działać. Mam taką procedurę:

procedure Draw;
begin
  Form1.PaintBox1.Canvas.Pen.Color:=clRed;
  Form1.PaintBox1.Canvas.MoveTo(200, 200);
  Form1.PaintBox1.Canvas.LineTo(100, 100);
  Form1.PaintBox1.Update;
end;

i w momencie wywołania jej na TPaintBox'ie widzę na 0,1 sekundy czerwoną linię. Tak to TPaintBox jest pusty. w OpenGL'u ciężko będzie to zrobić. Dlatego najpierw skorzystam z najprostszych rozwiązań (pobawię się trochę TStringGrid'em)

0
procedure TForm1.PaintBox1OnPaint(Ovner:TCOmponent); // podpiąć pod zdarzenie
begin
  PaintBox1.Canvas.Pen.Color:=clRed;
  PaintBox1.Canvas.MoveTo(200, 200);
  PaintBox1.Canvas.LineTo(100, 100);
end;

procedure Draw;
begin
  Form1.PaintBox1.Invalidate;
end;
0

@_13th_Dragon, dzięki za kod.
Bawiłem się TStringGridem i powiem, że w ogóle nie nadaje się do tego.
Został TPaintBox, nigdy w tym nie rysowałem więc, napisałem to tak:

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  Draw;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  iType := 0;
  PaintBox1.Invalidate;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  iType := 1;
  PaintBox1.Invalidate;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  iType := 2;
  PaintBox1.Invalidate;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  iType := 3;
  PaintBox1.Invalidate;
end;

procedure Draw;
begin

  if iType = 1 then
  begin
  Form1.PaintBox1.Canvas.Pen.Color := clRed;
  Form1.PaintBox1.Canvas.LineTo (20, 30);
  end else if iType = 2 then
  begin
  Form1.PaintBox1.Canvas.Pen.Color := clGreen;
  Form1.PaintBox1.Canvas.LineTo (40, 50);
  end else if iType = 3 then
  begin
  Form1.PaintBox1.Canvas.Pen.Color := clBlack;
  Form1.PaintBox1.Canvas.LineTo (50, 60);
  end else
  begin
  Form1.PaintBox1.Canvas.Pen.Color := clBlue;
  Form1.PaintBox1.Canvas.LineTo (70, 80);
  end;

end; 

Kod mniej więcej "działa". Pytanie da się jakoś to uprościć? Czy to jest dobrze napisane?
Czego potrzebuję:
Program musi narysować plansze: statków gracza i trafień.
Mogę "jakoś" użyć zdarzenia OnClick na PaintBox'ie i odczytywać współrzędne kursora zdarzeniem onMouseMove co pozwoliłoby mi na interakcję - głupie rozwiązanie i trudne ale da się napisać.
Muszę planszę zmieniać, czyli rysować prawie to samo, ale np. za drugim razem z wypełnionym na niebiesko jednym polem w planszy.

0

Zrobisz jak będziesz uważał. Ale jeżeli nie chcesz używać silników, co polecił Tobie @Patryk27, a robić to pod czystym Delphi. To oczywiscie można się męczyć PaintBoxem, ale nie wiem dlaczego przy braku wiedzy, upierasz się na niego, zamiast na zasugerowany wcześniej również TStringGrid. Jakie są jego plusy? Otóż że poza tym, iż łatwo sobie rysujesz "wodę", statek trafiony albo chybiony strzał, chocby: http://stackoverflow.com/questions/9924259/inserting-image-in-stringgrid-cell - gdzie wiadomo zamiast grafiki z TImage podstawiamy jakąś z zasobów. A poza swobodnym niemal rysowaniem komórek StringGrida posiada on jeszcze własności Objects. To daje Tobie możliwosć utworzenia jakiejś klasy bazowej na przykład TGameField, która obsłuży w przyszłosci wyswietlanie grafiki trafien i innej, odtwarzanie dźwięków (ja bym takie coś przewidział, co komu dzisiaj z niemej gry, a tak pakujemy sobie bass.dll do zasobów, używamy dllloader.pas, o ktorym niedawno pisałem tutaj przy okazji wątku o dołączeniu i korzystaniu z dllki do zosobów exeka i jazda) i reakcje gry na to czy już zatopiono nasze lub przeciwnika statki. I tak dalej. Tak bym kombinował. A i widze, że to chyba po raz kolejny odświeżenie tematu pisania gry "Statki" w Delphi. I tak się zastanawiam czy to na prawdę aż tak trudne zadanie. Wydaje mi się, że po przemyśleniu tematu jest to do ogarnięcia, a schody mogą się zacząć dopiero przy eleganckim obsłużeniu gry sieciowej czy implementacji sztucznej inteligencji CPU, o ile taką planujesz. A tak do testów na szybko z losowym celowaniem komputera to po prostu usiąść, pomyśleć i to napisać, nie mnożąć sobie zbędnie problemów na zaś :)

0
olesio napisał(a):

To oczywiscie można się męczyć PaintBoxem, ale nie wiem dlaczego przy braku wiedzy, upierasz się na niego, zamiast na zasugerowany wcześniej również TStringGrid.

@olesio, bardzo przepraszam ale chrzani waść. Co może być prostsze od PaintBox'a?
Ot całe rysowanie:

procedure TForm1.PaintBoxPaint(Sender: TObject);
var y,x:Integer;
begin
  for y:=0 to 9 do for x:=0 to 9 do ImageList.Draw(PaintBox.Canvas,x*32,y*32,Tb[y,x]);
end;

StringGrid nawet się nie umywa.

0

No można i tak. Teraz doczytałem, że to Lazarus, więc odpadają moje porady o takim użyciu bass.dll z zasobów, bo za pewne się okaże, że tam ten moduł jak to Lazarus ma w zwyczaju nie być kompatybilnym wstecz, nie zadziała. Ale nie sprawdzałem, więc i mozę się da jak nie tym, to innym. W sumie można mieć też i dwie tablice 10x10 na trzymanie obiektów do obsługi pola gry. Po prostu mi się wydawało, że pod TStringGrid to zrobić łatwiej. Tylko pytający nie zrobił chyba jeszcze nic i kombinuje z tą grą jak nie wiem z czym, zamiast przysiąść i zaprogramować to. A ja, że śmiałem polecić TStringGrid, to zaraz "chrzanie". Tylko już nieraz było tak, że ktoś na forum o coś spyta z tematyki Lazarus / Pascal / Delphi, to mimo iż mija kilkadziesiąt minut, a nie jest ani późno w nocy, ani wcześnie nad ranem, a i ja nie mam codziennie wolnego, to jakoś mogę odpisać. Najlepiej jest zwkleać z odpowiedzią, a innym zarzucać chrzanienie. Teraz to nie będe pisał nic, wątki będą bez odpowiedzi, a każdy kto podważy opinie Dragona będzie chrzanił. Niezłych czasów doczekaliśmy.

0

To może i ja coś od siebie dorzucę :P
W załączniku jest edytor poziomów do ramake'a gry Tower of The Sorcerer dla canvas HTML5.

Edytor był pisany w Delphi 5 na szybko do własnego użytku (w grze jest tylko 50 poziomów), ale możesz sobie zobaczyć jak łatwo jest zrobić rysowanie planszy i wyliczać współrzędne.

link do skompilowanego exe - nie wiem czy w lazarusie są wszystkie użyte komponenty
http://speedy.sh/KMynW/Project1.exe

0

Faktycznie, proste acz geniealne. Może i chrzaniłem, ale wydawało się mi, że przy użyciu TStringGrid będzie prościej. A Twój projekt @szopenfx przyda się w przyszłości. Dodalem go sobie po drobnych poprawkach do moich projektów z prefiksem NOT_MINE. Zbieram tak niektóre źródła tutaj, które mnie zaciekawią. A nie jest tego wiele, bo jak pewnie kojarzycie tylko ja miałem głównie wcześniej zwyczaj zapodawania na forum gotowców.

Tylko zastanawiam się czy mozolnie wczytałeś bitmapy do ImageList czy podzieliło je i tak ładnie dopasowało, bo u mnie po wczytaniu bitmapki robią się tak małe jak dla celów obrazków w TListView, a nie tak jak to u Ciebie samo [?] Delphi zrobiło?

0

@szopenfx, dzięki, twoim sposobem jest najprościej.
To tak, tworzę komponent TImage jemu w canvas moge wstawić obrazek TBitmap w pozycji x,y. (metoda draw).
Nie pozostaje mi nic innego jak stworzyć obrazek planszy i obrazki pól planszy. Takie pytanie, czy da się cofnąć metodę draw? W Canvas nie ma metody Undo ;)

0

Znowu sobie mnożysz problemy gdzie ich nie ma @shJeff. Nie wiem w czym problem żeby stworzyć tablicę ze zmiennymi klasy, o której wspominałem. Można w niej zdefiniowac zmienne jak Indeks obrazka po jego ustawieniu i po kliknięciu na undo. Tak ja bym kombinował. Zresztą układanie statków na planszy to jedyny według mnie etap gdzie można pozwolić na Undo, w przypadku właściwej gry to też można założyć. Ale wtedy się gracz może na swóje ostateczne strzały decydować w nieskończoność i je cofać. A i @furious programming zauażył błąd w kodzie @szopenfx'a. Oczywisćie nie problem to naprawić ustawiając SelectedIndex na taki sam, jak zwykły.

0

Bo tak to jest, jak się chce odizolować broń Boże od nauki czegokolwiek nowego...

Stwórz sobie PaintBox, zadeklaruj tablicę 10x10 (albo dwie - jeszcze z polem przeciwnika) o dowolnym wygodnym typie i na jej (ich) podstawie rysuj odpowiednie pola w komponencie; Gdzieś trzymaj informacje o ostatnim ruchu i jeśli gracz cofnie ruch to nie nie kombinuj z implementacją metody Undo w klasie kanwy, tylko przemaluj jeden kwadracik o współrzędnych z ostatniego ruchu (trzeymałbyś je w ww. zmiennej); Stwórz sobie też tablicę z grafikami dla odpowiednich stanów jedego kwadracika;

Możesz nawet szarpnąć się na klasę do obsługi pól gry i w niej przechowywać wszelkie informacje na temat położenia statków, ilości oddanych strzałów, ilości zniszczonych statków itd.; Uprościłoby to wiele problemów;

Poza tym proponowałbym przestać pytać - usiądź i zastanów się najpierw jak to ma działać.


olesio napisał(a)

A i @Furious Programming zauażył błąd w kodzie @szopenfx'a. Oczywisćie nie problem to naprawić ustawiając SelectedIndex na taki sam, jak zwykły.

Dodatkowo domalowałbym jakąś ramkę na grafice, żeby się wyróżniała :]

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