25.12.2012

Oma koodailuprojekti, osa III

Minne nokka näyttää

Nyt kun olin vihdoin saanut sekä kuvioni kierron kuntoon ja sen suunnankin vihdoin selville, perustoimista jäljellä oli liikkuminen. Ensimmäinen yritelmäni oli vallankin jälkikäteen ajateltuna naurettava: jos kulma osoitti johonkin pääilmansuuntaan, kyseinen suunta sai täyden nopeusmuutoksen - jos taas sille välille niin jonkun puolikkaan muutoksen kahteen pääsuuntaan jaettuna. Testatessa se näytti ensin hienolta, mutta hetken päästä huomasin, että "Heeeeei... tämähän nykii kääntyessä ja kaasuttaessa ihan omituisesti". Pienikin poikkeama 3π/2:sta muutti nopeutta aina täysillä johonkin väli-ilmansuuntaan. Hupsis.

Realistisempi nopeusmuutos

Hyvin pienen ruuduntuijottelun jälkeen pääparassani syttyi lamppu: jos vaikka käyttäisin noita hiton trigonometrisia funktioita kertomaan juuri tuon: tunnettu kulma ja nopeus voidaan kääntää kertomaan aiemmin ihmettelemäni Δx ja Δy -arvot... Eli sama temppu, mutta päinvastaiseen suuntaan. Onneksi tuon äkkäämiseen ei mennyt muutamaa minuuttia enempää.

tempspeed = Vector(self.speed.x, self.speed.y)
dy = math.fabs((math.sin(self._angle))*self._acceleration)
dx = math.fabs((math.cos(self._angle))*self._acceleration)

# ...


Toki tuossa pitää vielä tarkastella polygonin suunnan perusteella, ovatko Δx ja Δy positiivisia vai negatiivisia kukin, jotta kiihdytyksen voi asettaa oikein. Pääasia, että se näyttää hyvältä ainakin tällä hetkellä.

Partikkeliefektejä!

Pelkän kuvion "lennättely" tyhjällä ruudulla käy äkkiä tylsäksi. Näpertelin siis Star Control (tai Auts tai  V-Wing tai Wings) -henkisen kaasutteluefektin. Sen tarkemmin moottoripaikkoja miettimättä asetin* ne polygonini alakulmiin. Aina, kun kaasua painetaan, senhetkisiin koordinaatteihin pudotetaan palikat, jotka kuolevat pois muutaman syklin päästä ja elellessään haalistuvat vähitellen. Tekaisin samalla vaivalla testimielessä warppinapin, jota painamalla palikka siirretään keskelle pelialuetta. Aiempaan paikkaan luodaan räjähdyksenomaiseti kahdeksan eri suuntiin lentävää partikkelia. Efekti on hauska, vaikka itse sanonkin. Räjähdyksiin minä tuota meinasin oikeasti käyttää.

*) Teinpä kaukoviisaana sentään sellaisen toteutuksen, että heti halutessani voin nakata ne mihin lystää, niissä lukumäärissä kuin haluan. Noin suunnilleen. Ehkä vältän tyhmyysrefaktorointia tällä tavoin.

Kavereita ruudulle

Mitäpä sitä suurinpiirtein kolmion muotoisella roikaleellaan tekisi 2d-avaruudessa ja varppailisi eestaas, jollei siellä ole seuraa? Tylsistyisi äkkiä, sanon minä. Mahdollisesti typerä ideanikin lienee jo tässä vaiheessa kaikille selvä kuin pläkki. Sekaan heitettäisiin tietenkin asteroideja!
Olin kovin riemastunut, kun sain kahdeksankulmaiset satunnaisepämuodot ruudulle neljässä eri kokoluokassa, pyörimään hiljakseen joko vasta- tai myötäpäivään ja parin iteraation jälkeen myös lentämään omaan suuntaansa. Se oli upeaa.
Pröp pröp pröp
Minä ainakin olin tuosta ylpeä.

18.12.2012

Oma koodailuprojekti, osa II

Taisin viimeksi sanoakin, etten ole koskaan koettanut tehdä mitään kovin graafista, jollei opiskeluaikojen nelikulmioita tai palloja ruudulle oksentelevaa TurboC++ -tekelettä lasketa mukaan (ei, ei sitä lasketa). Ykkösongelmani iski siis silmille jo tässä vaiheessa. Nelikärkisen polygonini piirtäminen keskelle piirtoaluetta oli simppeliä, mutta sen siirtely...

Mutisen tässä omista oivallusaskeleistani kutakuinkin niin kuin niitä muistan ja missä on olevinaan edes jonkunlaista tolkkua. Laatua en takaa, kuten en yleensäkään ;)

Sijainti, kierto, siirto, piirto

Ensimmäinen yritykseni oli siis kovakoodattuja koordinaattipisteitä käyttävä roipe. Kuvittelin, että siitä olisi hyvä lähteä mutta voi voi, miten väärässä olinkaan. Ehkä vika oli omissa ensimmäisissä kiertometodeissani ja toimivilla olisi toiminutkin, mutta ehkä ei. Alkutilanne piirtyi ruudulle kauniisti, mutta yksikin kiertoliike hajoitti koko muodon ihan miten sattuu.

Nollapisteen kautta

Keksin jostain (ja työkaverin kanssa puhuttuani oletukseni osoittautui oikeanlaiseksi), että jospa kaikkien piirrettävien kuvioiden kulmapisteet asetettaisiin aina (0,0):n suhteen. Tällöin polygonin kierto toimisi aina samalla tavalla, kun ei tarvitsisi arpoa sijainnin kanssa pätkääkään. Ensin siis napataan polygonille kulmat aina samaan paikkaan, sitten niiden arvot siirretään kohdalleen, tässä tapauksessa keskelle piirtoaluetta ja piirretään näkyviin. Yksinkertaista ja varmaan lapsellisen alkeellistakin, mutta kukas tuon olisi minulle käynyt kertomassa?

Kaksiulotteisen koordinaatiston kierto

Minun matemattiset opintoni ovat vuosien takana ja olin ehdottomasti niitä rasittavia kakaroita jo peruskoulussa, jotka julistivat, etteivät ikinä tarvitse matematiikkaa, saati sitten trigonometriaa koulun jälkeen. Näin se taas nähtiin, ettei se ihan noin mene :)
Muutaman omituisen ja hölmön "teen itse"-henkisen yrityksen jälkeen törmäsin affiiniin kuvaukseen ja sehän olikin näppärä ja toteutus kutakuinkin suoraan kirjoitettava. Sille nakataan kunkin piirrettävän polygonin jokaisen kulman koordinaatit vuorollaan ja haluttu kiertokulma (luonnollisesti se on kaikille sama), paluuarvona saadaan uudet koordinaatit.

def rotate(self, angle):
        rotated_points = []
        for point in self._points:
            new_point = self.affine_transform(Vector(point.x, point.y), angle)
            rotated_points.append(new_point)       
        return rotated_points


def affine_transform(self, point, angle):
        temp_x = ((point.x * math.cos(angle)) + (point.y * math.sin(angle)))
        temp_y = ((-point.x * math.sin(angle)) + (point.y * math.cos(angle)))
        return Vector(temp_x, temp_y )



Hah! Seuraavat kannot kaskessani olivatkin tuo kulma (kohelsin asteiden ja radiaanien kanssa, omaa pohjatonta tyhmyyttäni siis). Suurin ja melkoista päänvaivaa aiheuttanut ongelma oli siis polygonini liikuttelu piirtopinnalla. Kääntely toimi, mutta kun koetin saada sitä liikkumaan kolmion kärjen suuntaan, se lähti liitämään kiinteästi toiseen yläkulmaan ja sen ohi. Jos yritin kääntää liikkuvaa kolmiota, se liikkui edelleen oikeaa yläkulmaa kohti, mutta kuin syöksykierteessä... gnaah.

Miten lasken, mihin suuntaan polygonini katsoo?

Typeränä virheenä numero 74 olin unohtanut paikalleen kovakoodatut "piirrä tuo keskelle kuvaruutua"-arvot ja toisena jäätyneenä käpynä oli aina sama kulma. Olin jostain saanut aikaan kuvion kiertokulman (eli mihin sen "nokka" osoittaa) laskentaan toteutuksen, joka oli vähän väärä. Laskin nimittäin jotain eri kylkien pituuksien ja niiden välisten kulmien perusteella - muuten kai ihan hienoa toimintaa, muttei se tässä auttanut.

Pienen googlettelun ja kevyen pään pöytään hakkaamisen perusteella ratkaisu olikin helpompi kuin mitä sopisi olettaa. Tai ainakin näin tyhmälle. Kun tiedetään kärkipisteen koordinaatit ja keskipisteen koordinaatit, voidaan niiden x- ja y-suuntaisten välimatkojen (Δx, Δy) perusteella laskea arctanilla koko roskan kulma radiaaneina.

Kai se jotain selventää, vaikka vähän epäilenkin :p


def calculate_angle(self, center, nose):
        dx = center.x - nose.x
        dy = center.y - nose.y       
        radian_angle = math.atan2(dy, dx)
        return radian_angle


Nerokkaan yksinkertaista, sanon minä. Tähän väliin näyttää tosin siltä, että kukaan ei jaksa lukea tästä enää enempää yhdellä istumalla, joten jatkan taas seuraavalla rundilla.

11.12.2012

Koodailuprojektin taustaa

Taustaa

Kaipa "kaikki" missään määrin ohjelmointia edes kokeilleet ovat miettineet, että oman pelin tekeminen olisi hienoa. Joskus aikanaan räpelsin jotain sekavia tekstiviritelmiä senaikaisen 486:n mukana tulleella QuickBasicilla, muttei niistä syntynyt ikinä mitään sen mainittavampaa. Suurin kanto kaskessani on tuossa vaiheessa ollut se, etten vaan osannut mitään mutten myöskään keksinyt etsiä mitään Basic-ohjekirjaa hyödyllisempää lähdettä, josta opetella.
Jostain kummallisesta syystä, varmaankin laiskuudestani, johtuen en myöskään ruvennut kikkailemaan pelien tekemistä myöskään sen jälkeen, kun olin opiskellut ohjelmointia ja jopa oppinutkin jotain. Ajoittain mielessä kävi kyllä, että pitäisi tehdä jotain. Jos ei muuta niin ihan vaan huvin vuoksi.

Python - Pygame

Työkaveri vinkkasi joskus Ruby-pohjaisesta Shoooes-palikasta, jota meinasin kokeillakin, mutten taas vaihteeksi saanut mitään oleellista aikaan. Sitten sekin jäi monen muun "hei kokeillaas tätä"-tyyppisen testin kanssa nurkkaan pölyttymään. Törmäsin joskus vuosi, puolitoista sitten rss-feedeissäni Pygame-kirjastoon Pythonille. Perinteitä kunnioittaen testailin jotain pientä oman aikani kunnes sekin vain jäi hyvien (lue: toteuttamiskelpoisten) ideoiden puutteen takia.

for idea in ideas:

Kun tyystin oman idiksen toteuttaminen ei ole se helpoin, mitäs sitten? Jäljitellään muita eli kiivetään niiden jättiläisten hartioille huitomaan. Työkaverini oli ruvennut sörkkimään jotain Roguelikeä kasaan joten se siitä tähän väliin (vaikken ollutkaan miettinyt mitään perusfantasiateemaa). Lapsuudessani pelasin kovasti epätoivoisen vaikeaa Xenon II: Megablastia ja myöhemmin loistavaa Tyriania.
Xenon II: Megablast

Siinä mielessä klassishenkisen shoot'em upin pysty- tai sivuskrollaavana kiinnosti kovasti sekin. Noissa ensimmäinen esiinnoussut kysymysmerkki oli tasojen kanssa tuunaaminen, joten jätin idikset edelleen korvan taakse kaiken muun saastan sekaan.

Tyrian
Hiekkalaatikkoilu sekä tietyntyyppinen avoimuus, valinnanvapaus ja yleinen satunnaisuus (= kaikki ei aina tapahdu samalla tavalla ja samassa järjestyksessä) on aina kutkuttanut. Totaalinen vaihtoehdottomuus ja eritoten (tiukat) aikarajat kiehuttavat kerrasta toiseen. Ei sillä, että tuosta olisi helpointa lähteä liikkeelle, mutta jostain on aloitettava.

Kiepsis

Rupesinpa sitten lähestymään asiaa toisesta päästä eli aiemmasta top-downista bottom-upiin, vaikken ehkä ihan tietoisesti vaan ennemminkin puolivahingossa. Näppäilin siis ihan uteliaisuuttani ympäriinsä ja katselin, mitä kaikkea tuolla Pygamella voi tehdä ja miten se tehdään. Parilla hassulla koordinaattipisteellä ja kevyellä päänrapsuttelulla pygame.draw.Polygon(...) toi kiehtovia tuloksia piirtopinnalle. "Hei, tuotahan voisi vaikka liikutella noiden näppäineventtien perusteella! Mites sen tekiskään..."

Mitä juoninkaan? Siitä kerron teille ensi viikolla.
Olen ilkeä tiiseri, tiedän. Hähä.

4.12.2012

Henk. koht. vaurioita

Tyhmästä päästä kärsii koko ruumis.

Mitä niillä nivelillä...


Särjin siis lautasen käsiini ja päädyin tikattavaksi. Tietysti pahimmat vauriot otin oikeaan peukalooni, joten rakenteluprojekti on kuivatelakalla hetken tai toisenkin. Kas kun tikkien poiston jälkeen alkaa olemaan vuosiloma kiireineen kohdalla, joten rakenteluaika on muutenkin kortilla tuohon aikaan. Saapa nähdä, miten tässä käy.