Kur planētām nav vietas. Lidinators v0.3
Nupat sapratu, ka lidināšanās apkārt nav nemaz tik interesanta. Tāpēc, turpinot lidinatora attīstību, nāksies to papildināt ar ko jaunu. Pirmais, kas man jau sākotnēji nepatika, ir tas, ka ļoti viegli nomaldīties un pazaudēt raķeti. Šo var risināt divejādi:
- Izdarīt tā, lai pie kāda taustiņa nospiešanas kuģis atgrieztos sākotnējā stāvoklī. Neforši, bet ļoti vienkārši.
- Neļaut kuģim izlidot ārpus ekrāna robežām. Nedaudz sarežģītāk, toties Īstu vīru solution™.
Lieki nedomājot izvēlējos otro variantu. Tā kā visa dzīve ir izvēlēšanās starp variantiem, tad arī šeit ir divi varianti, kā rīkoties gadījumā, ja kuģis sasniedz ekrāna malu. Viens būtu to "atsist" pret malu, kā biljarda bumbiņu, savukārt otrs veido "bezgalīgu" telpu, kad kuģis sasniedzot vienu malu parādās otrā. Ieraduma pēc atkal nolēmu, ka ir jāizvēlas otrais variants.
Nekas daudz jau šeit nav jādara, tik vien, kā jāizmaina kuģa koordinātes gadījumā, ja tā centrs ir aiz kādas no ekrāna robežām. Nedaudz jāpapildina Update() metode un lieta darīta
if (Math.Abs(shipLocation.X) > Window.ClientBounds.Width / 2)
{
shipLocation.X *= -1;
}
if (Math.Abs(shipLocation.Y) > Window.ClientBounds.Height /2 )
{
shipLocation.Y *= -1;
}
Tā, kā koordinātu sākumpunkts ir ekrāna centrā, tad pārbaude un koordināšu maiņa ir ļoti vienkārša. Pārbaudam, vai kādas koordinātes absolūtā vērtība nepārsniedz pusi atbilstošā ekrāna izmēra. Gadījumā, ja pārsniedz, tad šo koordināti pareizinot ar -1 kuģis tiek pārvietots uz otru ekrāna malu.
Šāda metode gan ir vienkāršota un gadījumā, ja kuģis apstājas tieši uz ekrāna malas, tad dabū diezgan nejauku mirgošanas efektu, tāpēc nākas to pārrakstīt nedaudz "gudrāk".
if (Math.Abs(shipLocation.X) > Window.ClientBounds.Width / 2)
{
float sign = Math.Abs(shipLocation.X) / shipLocation.X;
shipLocation.X = - 1 * sign *
Math.Min(Math.Abs(shipLocation.X), Window.ClientBounds.Width / 2 - 1);
}
if (Math.Abs(shipLocation.Y) > Window.ClientBounds.Height /2 )
{
float sign = Math.Abs(shipLocation.Y) / shipLocation.Y;
shipLocation.Y = -1 * sign *
Math.Min(Math.Abs(shipLocation.Y), Window.ClientBounds.Height / 2 - 1);
}
Nav tik saprotami, bet dara ko ļoti līdzīgu. Gadījumā, ja kuģis jāpārvieto uz otru ekrāna malu, tad izvēlas ekrāna centram tuvāko vērtību no kuģa koordinātes un punkta, kas ir par vienu vienību nost no ekrāna malas.
Tagad kuģi pazaudēt ir grūtāk, bet lidināšanās īpaši interesantāka nav palikusi. Lai nebūtu tik vientuļi, papildināsim pieejamo kosmosu ar kādu planētu.
Atkārtojot pirmajā rakstā minētās darbības, jāpievieno planētas gariņgrafiku projekta saturam. Tālāk nepieciešams izveidot mainīgos koordināšu un gariņa glabāšanai, spēles sākumā inicializēt planētas koordinātes un attēlot to uz ekrāna Draw() metodē. Tās visas ir jau apskatītas lietas, tāpēc detalizēti to neapskatīšu. Jebkurā gadījumā to var apskatīt pievienotajā pirmkodā.
Bet ja jau ir planēta, tad vajadzētu ļaut tajā ietriekties kuģim, lai lidošanai piedotu "briesmu elementu". Ja šajā spēles posmā kuģis "saduras" ar planētu, tad tas vienkārši pārlido pāri tā, it kā planēta atrastos tālumā. Šeit ir nepieciešams izmantot kādu sadursmju noteikšanas mehānismu, lai konstatētu, ka abi objekti ir sadūrušies.
XNA piedāvā vairākas struktūra, kuras var izmantot sadursmju noteikšanai. Lai gan šīs klases ir paredzētas izmantošanai 3D telpā, tās mierīgi var izmantot arī 2D spēlēs. Lidinatora piemērā tiek izmantota BoundingSphere struktūra, kas izmanto objektu aptverošu lodi. Tas gan nav precīzākais sadursmju noteikšanas veids, bet sākumā noderēs.
Update() metodē izveido divas jaunas BoundingSphere lodes, kas atbilst katram no objektiem (planētai un kuģim):
BoundingSphere shipSphere = new BoundingSphere(
new Vector3(shipLocation, 0),
(float)(shipSprite.Width / 2.5));
BoundingSphere planetSphere = new BoundingSphere(
new Vector3(planetLocation, 0),
(float)(planetSprite.Width / 2.5));
Lai pārbaudītu, vai lodes nepārklājas, jāizmanto Intersects() metode. Lai uzskatāmāk varētu redzēt kurā brīdī lodes pārklājas, nedaudz izmainīšu zīmēšanas metodi lai pārklāšanās gadījumā izmantotu sarkanu fonu. Šim nolūkam tiek izveidots jauns klases lauks kurā glabā pārbaudes rezultātu un Update() metodē to aizpilda ar pārbaudes rezultātu:
crashed = shipSphere.Intersects(planetSphere);
Un zīmēšanas izmaiņas:
GraphicsDevice.Clear(crashed ? Color.Red : Color.CornflowerBlue);
Kā rezultātā ir iespējams vērot nākošajā attēlā redzamo ainu.

Tas pirmajā tuvinājumā arī būtu viss par sadursmju noteikšanu. Katrā ziņā nākošajās sērijās ar to vēl nāksies saskarties ne vienu vien reizi.