Uf, to je hlavolam a ne program .
Zaprvé, chce to pojmenovávat proměnné nějak srozumitelně. Sice vidím, co se se kterou dělá, ale netroufám si odhadnout, jestli to je zrovna to, co chceme.
Zadruhé, jestli Pole obsahuje xové souřadnice lodí, Pola yové a Zivot jejich životy (resp. existenci nebo neexistenci), tak je to špatně, protože každé z těch polí je jinak velké. Jestli chceš ukládat souřadnice pro každou loď zvlášť, potřebuješ pro všechno stejná dvojrozměrná pole. Existuje datový typ Record, kterým by to šlo krásně zpřehlednit:
type info = record {tyhle údaje jsou stejné pro lodě i střely}
x,y:integer; {souřadnice}
zije:boolean; {jestli existuje nebo ne, možné hodnoty true nebo false}
end;
const pocet_lodi_x=10;
pocet_lodi_y=10;
pocet_strel=3;
var lode:array[0..pocet_lodi_y-1,0..pocet_lodi_x-1] of info;
strely:array[1..pocet_strel] of info;
Konstanty jsou taky výborná věc - když tě později napadne změnit nějaké číslo, přepíšeš jednu konstantu a je to, nemusíš procházet celý kód a hledat všechny výskyty daného čísla.
Od nuly pole indexuju jenom proto, aby se s nimi později lépe pracovalo. Teoreticky by mohly být klidně i od jedničky.
Jestli to ale děláš jako u klasických Space Invaders, kde se všechny lodě pohybují v pevné formaci, stačí ti jenom poloha jedné z nich (třeba levé horní, ať se to neplete) a 2D pole životů. Všechno ostatní dopočítáš za běhu v jednom 2D cyklu, například:
setcolor(barva_lodi);
for i:=0 to pocet_lodi_y-1 do {cyklus pres radky}
for j:=0 to pocet_lodi_x-1 do {cyklus pres sloupce}
if lode[i,j].zije then circle(leva_horni_x+vodorovna_roztec*i,
leva_horni_y+svisla_roztec*j,polomer_lode);
Tím máš hotové vykreslení všech existujících lodí. Použil jsem proměnnou Lode z minulého odstavce, ale teď už by nebyla potřeba - stačily by jenom samotné životy. Proměnné leva_horni_x/y jsou souřadnice levé horní lodě, které jako jediné by se během hry měnily.
Potom ten pohyb. Je zbytečné psát ho pro každý směr odděleně, stačí si uvědomit, co a jak se má hýbat: jeden bod, nejdřív 1) doprava, pak 2) dolů, 3) doleva, 4) dolů a zase od 1 dokola. Takže by pro celý pohyb všech lodí stačilo tohle:
const vodorovna_rychlost= o kolik pixelu se maji lode posunout v jednom cyklu pri vodorovnem pohybu;
svisla_rychlost= totez pro svisly pohyb;
vodorovny_rozsah_kroku= kolik cyklu maji lode letet vodorovne
svisly_krok= kolik cyklu maji klesat dolu
var smer:integer; {mozne hodnoty 1..4}
pocet_kroku:integer; {na pocitani uletnute vzdalenosti}
...
smer:=1; {zacneme treba smerem doprava}
leva_horni_x:= nejaka vhodna pocatecni souradnice
leva_horni_y:= nejaka vhodna pocatecni souradnice
pocet_kroku:=0;
...
repeat {hlavni cyklus}
...
{pohyb lodi podle aktualniho smeru:}
case smer of 1:inc(leva_horni_x,vodorovna_rychlost); {doprava}
2,4:inc(leva_horni_y,svisla_rychlost); {dolu}
3:dec(leva_horni_x,vodorovna_rychlost); {doleva}
end;
{zmena smeru po dosazeni urciteho poctu kroku:}
inc(pocet_kroku);
if (pocet_kroku>vodorovny_rozsah_kroku)
or (pocet_kroku>svisly_krok) and ((smer=2)or(smer=4))
then begin
inc(smer);
if smer>4 then smer:=1;
end;
...
until ...
...
Mimochodem, inc(x) je totéž co x:=x+1 a inc(x,n) je x:=x+n, s dlouhými jmény proměnných je to tak pohodlnější.
Kdybych směr počítal od 0 do 3, mohli bychom if nahradit výpočtem smer:=(smer+1) and 3 nebo smer:=(smer+1) mod 4, ale to už je detail.
Lodě bychom měli, teď střely:
for i:=1 to pocet_strel do
with strely[i] do
if zije then begin
setcolor(pozadi);
line(x,y,x,y+vyska_strely);
inc(y,rychlost_strel);
if y>810 then zije:=false
else begin
setcolor(barva_strely);
line(x,y,x,y+vyska_strely);
end;
end
else begin
x:= neco nahodneho
y:= neco nahodneho
zije:=true;
end;
Příkazem With jsem si naadresoval i-tou střelu, takže potom nemusím pořád opisovat strely[i].x, stačí jenom to x. Ale šlo by to i tak.
Hlavní je uvědomit si, kdy je střela ještě vidět a že kontrola polohy a případné "zabití" musí nastat v okamžiku, když vidět není, a následující vykreslení se provede jenom když ještě "žije".
Ještě jedna obecná věc. Ve výše uvedených příkladech předpokládám, že se hlavní cyklus hry točí v nějakých víceméně konstantních časových úsecích nezávislých na klávesnici, tj. že se klávesy vyhodnocují stylem if keypressed then begin klávesa:=readkey; vyhodnoť ji; end else nic. Jestli časování vyřešíš přes Delay nebo nějak líp, to už je celkem jedno.