Witam!
Ostatnio chciałem zrobić małą grę, ale mam z nią kłopot i chciałbym prosić o pomoc.
Od początku: Gra ma polegać na jeżdżeniu samochodzikiem i zbieraniu gwiazdek. Samochodzik jest przedstawiany za pomocą komponentu Image (wartość AutoSize ustawiona na true) i poruszany za pomocą Timer'ów (na przykład dla jeżdżenia w lewo:
procedure Tsam.tlewoTimer(Sender: TObject);
begin
paliwo(Sender); // procedura odejmująca lub dodająca paliwo
gwiazdka(Sender); // procedura sprawdzająca pozycję samochodziku i gwiazdki (o tym niżej)
// isam to nazwa Image'a z obrazkiem samochodziku
if isam.Left > 5 then
isam.Left := isam.Left - 1;
// poniższy zapis umożliwia "rozbicie" samochodu
if isam.Left <= 5 then begin
isam.Picture.LoadFromFile('kraksalewo.bmp');
przegrana(Sender); //procedura przerywająca grę
end;
end;
Dla pozostałych kierunków użyłem analogicznej jak wyżej procedury.)
Timer'y są uruchamiane za pomocą procedury OnKeyDown (ich nazwy to tdol, tgora, tlewo, tprawo):
procedure Tsam.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
{ k to zmienna globalna określające kierunek jazdy
Wprowadziłem zabezpieczenie polegające na tym, że
gdy zmienna k jest równa np. lewo, to nie można pojechać
od razu w prawo (byłoby to nienaturalne) }
if Key = vk_Left then begin
if k <> 'prawo' then begin
isam.Picture.LoadFromFile('samlewo.bmp');
tlewo.Enabled := true;
k := 'lewo'
end;
end;
if Key = vk_Right then begin
if k <> 'lewo' then begin
isam.Picture.LoadFromFile('samprawo.bmp');
tprawo.Enabled := true;
k := 'prawo';
end;
end;
if Key = vk_Up then begin
if k <> 'dol' then begin
isam.Picture.LoadFromFile('samgora.bmp');
tgora.Enabled := true;
k := 'gora';
end;
end;
if Key = vk_Down then begin
if k <> 'gora' then begin
isam.Picture.LoadFromFile('samdol.bmp');
tdol.Enabled := true;
k := 'dol';
end;
end;
end;
Ich wyłączenie umożliwia procedura OnKeyUp formatki:
procedure Tsam.FormKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
vk_Left : begin
tlewo.Enabled := false;
tpaliwominus.Enabled := false; // Timer powodujący utratę paliwa
end;
vk_Right : begin
tprawo.Enabled := false;
tpaliwominus.Enabled := false;
end;
vk_Up : begin
tgora.Enabled := false;
tpaliwominus.Enabled := false;
end;
vk_Down : begin
tdol.Enabled := false;
tpaliwominus.Enabled := false;
end;
end;
end;
Pozycję gwiazdki ustala procedura:
procedure Tsam.losujgwiazdke(Sender: TObject);
begin
Randomize;
// istar to nazwa Image'a z rysunkiem gwiazdki
istar.Left := Random(265) + 8;
istar.Top := Random(165) + 8;
istar.SendToBack;
isam.BringToFront;
{ poniższe zmienne określają punkty, według których
będzie sprawdzana pozycja samochodziku i gwiazdki
(ale o tym w innej procedurze). Zmienne te obowiązują
dla całego programu }
gl := istar.Left - 10;
gp := istar.Left + istar.Width + 10;
bg := istar.Top - 10;
bd := istar.Top + istar.Height + 10;
end;
Jest ona wywoływana na początku programu i po każdym "zdobyciu" gwiazdki.
Mój problem polega na procedurze sprawdzającej pozycję samochodu i gwiazdki, oraz jej "zdobycie".
Procedura wygląda tak:
procedure Tsam.gwiazdka(Sender: TObject);
var
x, iw, ih : Integer;
begin
x := StrToInt(lgwiazdki.Caption); //pobiera liczbę z Label'a (liczba zdobytych gwiazdek)
iw := isam.Width; // zmienna określająca szerokość Image'a z samochodzikiem
ih := isam.Height; // zmienna określająca wysokość Image'a z samochodzikiem
if x >= 10 then begin // po zdobyciu 10 gwiazdek
wygrana(Sender); // następuje wygrana
Exit; // i koniec procedury
end else begin // jeżeli zdobyłeś mniej niż 10 gwiazdek:
{ k to zmienna globalna (typu String) określająca kierunek jazdy,
zmienne gl, gp, bg i bd były opisane w procedurze losującej
pozycję gwiazdki }
if k = 'prawo' then begin
if ((isam.Left + isam.Width) in [gl..gp]) and (isam.Top in [(bg-ih)..bd]) then begin
x := x + 1;
lgwiazdki.Caption := IntToStr(x);
losujgwiazdke(Sender); //procedura losująca pozycję gwiazdki
Exit; // koniec tej procedury
end;
end;
if k = 'lewo' then begin
if (isam.Left in [gl..gp]) and (isam.Top in [(bg-ih)..bd]) then begin
x := x + 1;
lgwiazdki.Caption := IntToStr(x);
losujgwiazdke(Sender);
Exit;
end;
end;
if k = 'gora' then begin
if (isam.Left in [(gl-iw)..gp]) and (isam.Top in [bg..bd]) then begin
x := x + 1;
lgwiazdki.Caption := IntToStr(x);
losujgwiazdke(Sender);
Exit;
end;
end;
if k = 'dol' then begin
if (isam.Left in [(gl-iw)..gp]) and ((isam.Top + isam.Height) in [bg..bd]) then begin
x := x + 1;
lgwiazdki.Caption := IntToStr(x);
losujgwiazdke(Sender);
Exit;
end;
end;
end;
end;
Powyższa procedura raz sprawia, że gwiazdka znika i pojawia się w innym miejscu, a innym razem nie działa. Tak jakby w pewnych miejscach nie mogła zadziałać.
Czy da się to jakoś poprawić, tak, aby zawsze "zebrać" gwiazdkę?
Z góry dziękuję.