25.12.2013

Oma koodailuprojekti, osa VII

Pitkän tauon jälkeen

Pygame-projektini on edennyt enemmän kuin mitä postaustahdista voisi olettaa. Pääasiassa olen räveltänyt taustapalikoiden kanssa, mitään kovin näkyvää tai käyttäjälle suoraan (ainakaan vielä) näkyvää en niinkään.
Toisaalta, jos edellispostausta aiheen tiimoilta katsoo, aikalaillahan tässä on muuttunut.

Viimeksi siis pelimaailma sektoreineen luotiin ja sen perusteella käyttäjälle (tässä vaiheessa ei ole mitään pelattavaa, joten en saata kutsua sitä "pelaajaksi") näytettiin kartta. Kartan sai avata/sulkea ja pelin pystyi pistämään tauolle. Perustoimintoja, muttei mitään kovin hienoa tai ihmeellistä.

Jatkoaskeleet

Ensimmäisen iteraation pelinäkymä oli kiinteä ja alus lensi siinä vapaasti. Ensimmäinen asia oli siis aluksen kiinnittäminen näytettävän alueen (viewport) keskelle ja sen vierittäminen eestaas ympäri pelialuetta (sektoria). Koska sektorin koko olisi aina näyttöaluetta laajempi, ei olisi myöskään mitään tolkkua piirrättää sellaisia objekteja, jotka eivät ole näyttöalueen sisällä. Sektorilla olisi siis oltava jonkunlainen tietorakenne peliobjektejaan varten, josta tuonkin tiedon saisi kaivettua esiin.

QuadTree

QuadTreen idea on, että jos sen yksittäisen solun kapasiteetti ylitetään, se jakautuu neljään alisoluun, johon kaikki sen sisältämät objektit jaetaan edelleen alisolujen sisään. Ja niin edelleen, kunnes puun maksimisyvyys on saavutettu. Mikään selitykseni ei voi olla parempi kuin jo olemassaolevat, joten vaikkapa wikipediasta voi lukea lisää.
Oleellista on se, että toteutin oman (tai tässä vaiheessa osan siitä) versioni tuosta. Alkuvaiheessa, kun sen pelkkä olemassaolo riittää hyvin, kaikki sektoriin kuuluva romu lisätään puuhun. Yllämainittu tarve näyttöalueella olevien peliobjektien hakemisesta taas oli ensimmäinen oikea käyttötapaus. Koska sektorit ovat neliöitä, kaikki peliobjektini toimivat ainakin tässä vaiheessa neliöinä ja nelipuun kaikki solut ovat luonnollisesti neliöitä, pygamen colliderect-metodit ratkaisevat kaiken.

def get_contained_objects(self, rectangle):
  contained_objects = []
  if self.gameobjects:
    for gameobject in self.gameobjects:
      if rectangle.colliderect(gameobject.get_rect()):
        contained_objects.append(gameobject)
      if self.top_left:
        contained_objects.extend(self.top_left.get_contained_objects(rectangle))
        contained_objects.extend(self.top_right.get_contained_objects(rectangle))
        contained_objects.extend(self.bottom_right.get_contained_objects(rectangle))
        contained_objects.extend(self.bottom_left.get_contained_objects(rectangle))
  return contained_objects

Oleellista ylläolevassa on välitetty rectangle, joka on siis pelinäkymä (viewport). Pelinäkymän pinta-ala taas kaivetaan pelaajan aluksen keskipisteen ympäriltä. Samalla vaivalla lasketaan aluksen keskipisteen ja kuvapinta-alan 0,0-pisteen välinen poikkeama, jota taas käytetään palautettujen peliobjektien renderöintiin. Kaikkien peliobjektien sijainti kartalla (sektorissa) on suhteessa sen vasempaan yläkulmaan ja siksi tuota poikkeamaa tarvitaan, jotta ko. peliobjekti voidaan piirtää oikeaan paikkaan suhteessa pelaajan alukseen.

Ehkä selitin tämänkin taas turhan oudosti, mutta minkäs teet. Koko ongelman selvittämiseen meni muutamakin istunto ja tuokio. Olin siis hyvin ylpeä, kun sain asiat vihdoin toimimaan oikein.



Peliobjektien paluu

Tietysti minulla piti olla jotain piirrettävää, jotta sain nelipuuni toiminnan testattua edes alkeellisesti. Alkuvaiheessa minulla oli nuo viimeksikin mainitut kolme aliavaruuspiraattien alusta heitettynä vakiopisteisiin sektorissa. Niiden lisäksi halusin tietysti palauttaa Asteroidit mukaan kuvaan, mutta tälläkin kerralla vähän paremmin. Samalla vaivalla puun insert- ja jakautumismetodeja voisi testata satunnaismäärällä sisältöä.

Asteroidikoodi siirtyi lähes sellaisenaan uuteen projektiin. Inittiin tuli lähinnä lisää satunnaisuutta. 2d6-heiton tuloksella 9-12 syntyy jääasteroidi, muuten kivinen murikka. Samoin 2d6-heitolla määritellään murkulan kokoluokka vanhoilla tutuilla pieni / keskikokoinen / iso / suunnaton -vaihtoehdoilla. Materiaali vaikuttaa sekä väriin, satunnaisarvottuun massaan että pyörimisnopeuteen. Kiviset ovat sekä raskaampia että hitaampia kuin jäiset asteroidit.



Ei kommentteja:

Lähetä kommentti